我正面临一个我找不到合适而优雅的解决方案的问题。我有List
Videos
,这是一个包含视频信息的类。在这些信息中,有startDate
,endDate
和cameraId
属性。
我当前的数据库具有以下值:
startDate endDate
我想迭代这些值,当视频与最后一个视频相差5分钟并且具有相同的cameraId
时,它应该被计为一个。但是我找不到一种合适而不优雅的方法来完成这项任务。
上面显示的视频列表的输出应为
这是我到目前为止的代码:
private void ProcessVideos(List<Video> videos)
{
bool isSameVideo = false;
Video lastVideo = null;
//debugar e ver esquema do ultimo valor do database
DateTime startDate = DateTime.MinValue;
DateTime endDate = DateTime.MinValue;
for (int i = 1; i < videos.Count; i++)
{
TimeSpan timeSpan = new TimeSpan(videos[i].DataInicio.Ticks - videos[i - 1].DataFim.Ticks);
if (timeSpan.Minutes > 0 && timeSpan.Minutes < 5 && videos[i].IdCamera == videos[i - 1].IdCamera)
{
if (!isSameVideo)
{
isSameVideo = true;
startDate = videos[i - 1].DataInicio;
endDate = videos[i].DataFim;
}
else
{
endDate = videos[i].DataFim;
}
}
else
{
if (isSameVideo)
{
i++;
isSameVideo = false;
Debug.WriteLine("inicio: {0} fim: {1}", startDate, endDate);
startDate = DateTime.MinValue;
endDate = DateTime.MinValue;
}
Debug.WriteLine("inicio: {0} fim: {1}", videos[i - 1].DataInicio, videos[i - 1].DataFim);
}
}
if (startDate != DateTime.MinValue)
{
Debug.WriteLine("inicio: {0} fim: {1}", startDate, endDate);
}
}
主要问题是:根据时间跨度规范迭代这些值并输出值的组合有什么好的逻辑?
答案 0 :(得分:1)
我创建了一个小例子来向您展示:
我的容器对象:
internal class Container
{
public int Id { get; set; }
public DateTime Start { get; set; }
public DateTime Stop { get; set; }
public override string ToString()
{
return "ID " + Id + ": " + Start + " -> " + Stop;
}
}
我的方法:
private static IEnumerable<Container> DoMerge(List<Container> elements, TimeSpan maxDiff)
{
var closedContainers = new List<Container>();
var lastContainers = new Dictionary<int, Container>();
foreach (Container container in elements.OrderBy(e => e.Start))
{
//First case, no previous container
if (!lastContainers.ContainsKey(container.Id))
{
lastContainers[container.Id] = container;
}
else if (container.Start - lastContainers[container.Id].Stop > maxDiff)
//We have a container, but not in our windows of 5 minutes
{
closedContainers.Add(lastContainers[container.Id]);
lastContainers[container.Id] = container;
}
else
{
//We have to merge our two containers
lastContainers[container.Id].Stop = container.Stop;
}
}
//We have now to put all "lastContainer" in our final list
foreach (KeyValuePair<int, Container> lastContainer in lastContainers)
{
closedContainers.Add(lastContainer.Value);
}
return closedContainers;
}
我们只需要给出最大时间跨度和元素列表:
private static void Main(string[] args)
{
var elements = new List<Container>
{
new Container {Id = 1, Start = new DateTime(2013, 3, 1, 18, 25, 26), Stop = new DateTime(2013, 3, 1, 18, 27, 29)},
new Container {Id = 1, Start = new DateTime(2013, 3, 1, 18, 30, 26), Stop = new DateTime(2013, 3, 1, 18, 34, 29)},
new Container {Id = 1, Start = new DateTime(2013, 3, 1, 18, 40, 26), Stop = new DateTime(2013, 3, 1, 18, 52, 29)},
new Container {Id = 1, Start = new DateTime(2013, 3, 1, 18, 55, 26), Stop = new DateTime(2013, 3, 1, 18, 59, 29)},
};
foreach (Container container in DoMerge(elements, TimeSpan.FromMinutes(5)))
{
Console.WriteLine(container);
}
Console.ReadLine();
}
这给了我预期的结果我们两个对象左。
提及数据的结果:
答案 1 :(得分:0)
这是一个解决方案。 ExtractVidTimes方法显示了该方法的关键。其余的只是用于创建样本数据
[TestFixture]
public class TestyMcTest
{
public class Vid
{
public int CamId;
public DateTime Start;
public DateTime End;
}
[Test]
public void Test()
{
var list = new List<Vid>
{
//=====Combination1=======
new Vid
{
CamId = 1,
Start = new DateTime(2000, 1, 1, 0, 0, 0),
End = new DateTime(2000, 1, 1, 0, 3, 0)
},
new Vid
{
CamId = 1,
Start = new DateTime(2000, 1, 1, 0, 5, 0),
End = new DateTime(2000, 1, 1, 0, 7, 0)
},
//=====Combination2=======
new Vid
{
CamId = 1,
Start = new DateTime(2000, 1, 1, 0, 15, 0),
End = new DateTime(2000, 1, 1, 0, 18, 0)
},
//=====Combination3=======
new Vid
{
CamId = 2,
Start = new DateTime(2000, 1, 1, 0, 0, 0),
End = new DateTime(2000, 1, 1, 0, 3, 0)
},
//=====Combination4=======
new Vid
{
CamId = 2,
Start = new DateTime(2000, 1, 1, 0, 10, 0),
End = new DateTime(2000, 1, 1, 0, 13, 0)
}
};
//here is your list of vids grouped by the cam id
var result = ExtractVidTimes(list);
}
//THE METHOD
private static List<List<Vid>> ExtractVidTimes(List<Vid> list)
{
//Group by cam ID
var vidGroups = list.GroupBy(vid => vid.CamId).ToList();
//extract vids with aggregate times
var result = vidGroups.Select(vids =>
{
var vidTimes = new List<Vid>();
var finalVid = vids.OrderBy(vid=> vid.Start).Aggregate((a, b) =>
{
if (a.End.AddMinutes(5) > b.Start)
{
a.End = b.End;
return a;
}
vidTimes.Add(a);
return b;
});
vidTimes.Add(finalVid);
return vidTimes;
}).ToList();
//return result.SelectMany(x=>x); //if you want a List<vid> return ed instead of a nested list
return result;
}
}