C#从List <List >中删除重复项

例如,我无法想出最有效的算法来从List<List>删除重复项(我知道这看起来像是int[]的列表,但只是为了视觉目的而这样做:

 my_list[0]= {1, 2, 3}; my_list[1]= {1, 2, 3}; my_list[2]= {9, 10, 11}; my_list[3]= {1, 2, 3}; 

所以输出就是

 new_list[0]= {1, 2, 3}; new_list[1]= {9, 10, 11}; 

如果您有任何想法,请告诉我。 我真的很感激。

构建EqualityComparer>自定义:

 public class CusComparer : IEqualityComparer> { public bool Equals(List x, List y) { return x.SequenceEqual(y); } public int GetHashCode(List obj) { int hashCode = 0; for (var index = 0; index < obj.Count; index++) { hashCode ^= new {Index = index, Item = obj[index]}.GetHashCode(); } return hashCode; } } 

然后,您可以使用Distinct with custom comparer方法获得结果:

 var result = my_list.Distinct(new CusComparer()); 

编辑:

将索引包含在方法GetHashCode以确保不同的订单不相​​等

这个简单的程序可以满足您的需求:

 using System; using System.Collections.Generic; using System.Linq; namespace ConsoleApplication6 { class Program { static void Main(string[] args) { List> lists = new List>(); lists.Add(new List { 1, 2, 3 }); lists.Add(new List { 1, 2, 3 }); lists.Add(new List { 9, 10, 11 }); lists.Add(new List { 1, 2, 3 }); var distinct = lists.Select(x => new HashSet(x)) .Distinct(HashSet.CreateSetComparer()); foreach (var list in distinct) { foreach (var v in list) { Console.Write(v + " "); } Console.WriteLine(); } } } } 
  var finalList = lists.GroupBy(x => String.Join(",", x)) .Select(x => x.First().ToList()) .ToList(); 

您可以使用带有比较器的LINQ Distinct重载。 比较器应该查看列表是否相等。 请注意,默认等于列表的操作将不会执行您真正想要的操作,因此比较器将需要为您循环。 这是一个这样的比较器的例子:

 public class SequenceComparer : IEqualityComparer> { IEqualityComparer itemComparer; public SequenceComparer() { this.itemComparer = EqualityComparer.Default; } public SequenceComparer(IEqualityComparer itemComparer) { this.itemComparer = itemComparer; } public bool Equals(IEnumerable x, IEnumerable y) { if (object.Equals(x, y)) return true; if (x == null || y == null) return false; return x.SequenceEqual(y, itemComparer); } public int GetHashCode(IEnumerable obj) { if (obj == null) return -1; int i = 0; return obj.Aggregate(0, (x, y) => x ^ new { Index = i++, ItemHash = itemComparer.GetHashCode(y) }.GetHashCode()); } } 

更新:我想到了使用匿名类型从Cuong Le的答案中获得更好的哈希值,并且我对它进行了LINQ-ified并使其在我的课堂上运行。

对于小型数据集,比较器可能很有用,但如果您有1000个或更多List>然后尝试比较它们,则所有这些都可能开始花费很长时间。

我建议你改用数据来构建一个独特的树。 树的构建将更快,当您完成后,您始终可以将数据恢复到旧的数据结构中。

我想比较一下@Leniel Macaferi和@LB答案的表现,因为我不确定哪个性能更高,或者差异是否显着。 事实certificate,差异非常显着:

 Method 1: 00:00:00.0976649 @Leniel Macaferi Method 2: 00:00:32.0961650 @LB 

这是我用来对它们进行基准测试的代码:

 public static void Main(string[] args) { var list = new List> {new List {1, 2, 3, 1, 2, 3, 1, 2, 3, 1, 2, 3, 1, 2, 3, 1, 2, 3, 1, 2, 3, 1, 2, 3, 1, 2, 3, 1, 2, 3, 1, 2, 3,}, new List {1, 2, 31, 2, 3, 1, 2, 3, 1, 2, 3, 1, 2, 3, 1, 2, 3, 1, 2, 3, 1, 2, 3, 1, 2, 3, 1, 2, 3, 1, 2, 3, 6}, new List {1, 2, 3, 1, 2, 3, 1, 2, 3, 1, 2, 3, 1, 2, 3, 1, 2, 3, 9, 10, 11, 1}, new List {1, 2, 3, 1, 2, 3, 1, 2, 3, 1, 2, 3, 1, 2, 3, 1, 2, 3, 1, 2, 3, 1, 2, 3, 1, 2, 3, 1, 2, 3, 1, 2, 3, 9}, new List {1, 2, 31, 2, 3, 1, 2, 3, 1, 2, 3, 1, 2, 3, 1, 2, 3, 1, 2, 3, 1, 2, 3, 1, 2, 3, 1, 2, 3, 1, 2, 3, 6, 7}, new List {1, 2, 3, 1, 2, 3, 1, 2, 3, 1, 2, 3, 1, 2, 3, 1, 2, 3, 9, 10, 11}, new List {1, 2, 3, 1, 2, 3, 1, 2, 3, 1, 2, 3, 1, 2, 3, 1, 2, 3, 1, 2, 3, 1, 2, 3, 1, 2, 3, 1, 2, 3, 1, 2, 3,}, new List {1, 2, 31, 2, 3, 1, 2, 3, 1, 2, 3, 1, 2, 3, 1, 2, 3, 1, 2, 3, 1, 2, 3, 1, 2, 3, 1, 2, 3, 1, 2, 3, 6}, new List {1, 2, 3, 1, 2, 3, 1, 2, 3, 1, 2, 3, 1, 2, 3, 1, 2, 3, 9, 10, 11}}; var sw1 = new Stopwatch(); sw1.Start(); for (var i = 0; i < 1_000_000; i++) { var distinct = list.Select(x => new HashSet(x)).Distinct(HashSet.CreateSetComparer()); } sw1.Stop(); Console.WriteLine($"Method 1: {sw1.Elapsed}"); var sw2 = new Stopwatch(); sw2.Start(); for (var i = 0; i < 1_000_000; i++) { var distinct = list.GroupBy(a => string.Join(",", a)).Select(a => a.First()).ToList(); } sw2.Stop(); Console.WriteLine($"Method 2: {sw2.Elapsed}"); Console.ReadKey(); }