2013-03-11 90 views
1

我正面臨一個問題,我無法找到一個適當和優雅的解決方案。我有一個ListVideos,這是一個包含有關視頻信息的類。在這些信息中有startDate,endDatecameraId財產。DateTime處理方法

我當前的數據庫具有以下值:

  startDate  endDate 

current database

我想通過這些值來迭代,並當視頻是從最後一個5分鐘差之內,並且具有相同cameraId它應該算作一個。但是我找不到一個合適的,不錯的方法來完成這項任務。

上面顯示的視頻列表的輸出應該

  • 第一:2013:03:01十八點25分26秒 - > 2013-03-01十八點34分29秒
  • 第二:2013 :03:01十八時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); 
      } 
     } 

的主要問題是:什麼是一個好的 邏輯來迭代這些值並根據時間跨度規格輸出一組值?

+0

棘手的部分是當你的數據混合。像camera1,camera2,camera1,camera3,camera1。我會用高峯期戰略。期待找到實際的結束日期。然後,您可以添加一個「已使用」的布爾值來「標記」那些已經使用過的布爾值,因此您不會打印重複的內容......您可以刪除列表中的「使用」列表,但從集合中刪除迭代是另一種蠕蟲......注意:在峯值前進時,你只需提前到達峯值,直到你退出5分鐘的窗口然後停止。 – 2013-03-11 12:27:32

+1

只需按日期排序()視頻。現在很簡單。 – 2013-03-11 12:35:48

+0

如果有多臺攝像機,則不需要按日期排序。 – 2013-03-11 12:48:49

回答

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

這給我你的預期結果,我們兩個對象左派。

結果與mentionned數據: enter image description here

+0

我實現了它,但它只輸出第一個視頻:start:03/01/2013 18:25:26 stop:03/01/2013 18:34:29 – 2013-03-11 13:08:52

+0

您確定要測試嗎?因爲如果我把所有的代碼都寫下來了,我真的會得到兩個時間段,就像我在我的回答中一樣 – J4N 2013-03-11 13:21:08

+0

我只是將代碼粘貼到一個新項目上,而且工作完美,我一定犯了錯誤。謝謝。 – 2013-03-11 13:22:21

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; 
    } 
} 
+0

編輯修復排序 – VARAK 2013-03-11 13:15:59