1

我面临一个问题,我找不到合适而优雅的解决方案。我有一个Listof Videos,这是一个包含有关视频信息的类。在这些信息中有一个startDate,endDate和一个cameraId属性。

我当前的数据库具有以下值:

         startDate      endDate

当前数据库

我想遍历这些值,当一个视频与上一个视频相差 5 分钟以内并且具有相同的值时,cameraId它应该算作一个。但我找不到完成这项任务的适当或优雅的方式。

上面显示的视频列表的输出应该是

  • 第一次:2013:03:01 18:25:26 -> 2013-03-01 18:34:29
  • 第二次:2013:03:01 18:40:26 -> 2013:03:01 18:59:29

这是我到目前为止的代码:

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);
            }
        }

主要问题是:遍历这些值并根据时间跨度规范输出值组合的良好逻辑是什么?

4

2 回答 2

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();
    }

这给了我我们两个对象留下的预期结果。

结果与提到的数据: 在此处输入图像描述

于 2013-03-11T12:35:36.063 回答
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;
    }
}
于 2013-03-11T13:06:08.510 回答