2016-04-14 82 views
0

我有一個對象列表(exobject在下面的代碼示例中),每個對象具有SomeId,AnotherId,SomeOtherId和Timestamp。該列表可能具有重複條目,每個記錄具有不同的時間戳。 我想用舊時間戳刪除這個對象的所有重複項,只保留那些最新的。根據C#中的條件刪除列表<T>中的重複項

樣本對象:

SomeId AnotherId SomeOtherId Timestamp 
1   2   1    10 
1   2   1    20 
1   3   2    30 
2   3   4    40 
1   3   2    50 

我的要求清單應

1,2,1,20 and 1,3,2,50 and 2,3,4,40. 

我在C#中一種非常原始的實現也這樣做。

for (int i = 0; i < exObject.Count - 1; i++) 
{ 
    for (int j = i + 1; j < exObject.Count - 1; j++) 
    { 
     if (exObject[i].SomeId == exObject[j].SomeId && exObject[i].AnotherId == exObject[j].AnotherId && exObject[i].SomeOtherId == exObject[j].SomeOtherId) 
     { 
      if (exObject[i].TimeStamp < exObject[j].TimeStamp) 
       exObject[i].TimeStamp = exObject[j].TimeStamp; 
      exObject.Remove(exObject[j]); 
     } 
    } 
} 

我想知道是否有一個更優雅的和更好的方式來做到這一點,或者如果有一個lambda我可以用它來實現這一目標。

+0

你不想使用exObject.Distinct()? – Damirchi

+0

我正在嘗試不同的方法。 – yazz

回答

1

System.Linq的具有獨特的方法。你必須實現一個IEqualityComparer。如何在這裏詳細...

https://msdn.microsoft.com/en-us/library/bb338049(v=vs.110).aspx


編輯根據您的評論:如果你做一個排序依據它應該讓你想要的......這裏的一些代碼...

using System.Collections.Generic; 
using System.Linq; 

namespace ConsoleApplication1 
{ 
    class Program 
    { 
     static void Main(string[] args) 
     { 
      var data = new[] 
      { 
       new SomeClass { SomeId = 1, AnotherId = 1, SomeOtherId = 1, Timestamp = 10 }, 
       new SomeClass { SomeId = 1, AnotherId = 1, SomeOtherId = 1, Timestamp = 20 }, // Duplicate 
       new SomeClass { SomeId = 1, AnotherId = 2, SomeOtherId = 2, Timestamp = 30 }, 
       new SomeClass { SomeId = 1, AnotherId = 2, SomeOtherId = 2, Timestamp = 35 }, // Duplicate 
       new SomeClass { SomeId = 2, AnotherId = 4, SomeOtherId = 4, Timestamp = 40 }, 
       new SomeClass { SomeId = 3, AnotherId = 2, SomeOtherId = 2, Timestamp = 50 }, 
       new SomeClass { SomeId = 1, AnotherId = 1, SomeOtherId = 1, Timestamp = 50 } // Duplicate 
      }; 

      var distinctList = data 
         .OrderBy(x => x.Timestamp) 
         .Distinct(new SomeClassComparer()) 
         .ToList(); 
      } 

     public class SomeClass 
     { 
      public int SomeId { get; set; } 
      public int AnotherId { get; set; } 
      public int SomeOtherId { get; set; } 
      public int Timestamp { get; set; } 
     } 

     public class SomeClassComparer : IEqualityComparer<SomeClass> 
     { 
      public bool Equals(SomeClass x, SomeClass y) 
      { 
       if (ReferenceEquals(x, y)) 
       { 
        return true; 
       } 

       //Check whether any of the compared objects is null. 
       if (ReferenceEquals(x, null) || ReferenceEquals(y, null)) 
       { 
        return false; 
       } 

       //Check whether the SomeClass's properties are equal. 
       return x.SomeId == y.SomeId && 
         x.AnotherId == y.AnotherId && 
         x.SomeOtherId == y.SomeOtherId; 
      } 

      public int GetHashCode(SomeClass someClass) 
      { 
       //Check whether the object is null 
       if (ReferenceEquals(someClass, null)) 
       { 
        return 0; 
       } 

       //Get hash code for the fields 
       var hashSomeId = someClass.SomeId.GetHashCode(); 
       var hashAnotherId = someClass.AnotherId.GetHashCode(); 
       var hashSomeOtherId = someClass.SomeOtherId.GetHashCode(); 

       //Calculate the hash code for the SomeClass. 
       return (hashSomeId^hashAnotherId)^hashSomeOtherId; 
      } 
     } 
    } 
} 
+0

我試着實現這個,但是如何在時間戳上添加條件?爲了刪除具有較舊時間戳的記錄? – yazz

+0

這與我目前的工作實現類似。非常感謝。 – yazz

0

可以羣由3個字段,並採取各組的第一個:

List 
    .GroupBy(x=> new {x.prop1, x.prop2, x.prop3 }) 
    .Select(g=> g.OrderByDescending(o=> o.dateprop).First()) 
    .ToList(); 

樣品被正常使用:

static void Main(string[] args) 
{ 
    List<Foo> myList = new List<Foo>(); 
    myList.Add(new Foo(1, 2, 1, 10)); 
    myList.Add(new Foo(1, 2, 1, 20)); 
    myList.Add(new Foo(1, 3, 2, 30)); 
    myList.Add(new Foo(2, 3, 4, 40)); 
    myList.Add(new Foo(1, 3, 2, 50)); 

    // The following returns 3 results with 20, 50 and 40 timeStamps. 

    var results = myList.GroupBy(x => new { x.SomeId, x.AnotherId, x.SomeOtherId }) 
          .Select(g => g.OrderByDescending(o => o.Timestamp).First()).ToList(); 

} 
+0

第一個將是該記錄的首次出現。但它可能不是最新時間戳的記錄。即具有較舊時間戳的記錄可以在列表中稍後出現。我是lambda新手 - 是否有GroupBy和OrderByDesc的組合?請提供一段代碼片段。 – yazz

+0

然後你可以按日期排序字段,然後取第一個 – user3185569

+0

檢查更新的答案。 – user3185569