C#从列表中删除重复项<;列表<;int>&燃气轮机;
例如,我很难想出从C#从列表中删除重复项<;列表<;int>&燃气轮机;,c#,list,duplicates,removeall,C#,List,Duplicates,Removeall,例如,我很难想出从列表中删除重复项的最有效算法(我知道这看起来像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}; 如果您有任何想法,请告诉我。我将非常感谢。您可以使用需要比较器的LINQ重载。比较
列表中删除重复项的最有效算法(我知道这看起来像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};
如果您有任何想法,请告诉我。我将非常感谢。您可以使用需要比较器的LINQ重载。比较器应该查看列表是否相等。请注意,列表的默认等于操作不会执行您真正想要的操作,因此比较器需要为您循环每个操作。下面是suc的一个示例h比较器:
public class SequenceComparer<T> : IEqualityComparer<IEnumerable<T>>
{
IEqualityComparer<T> itemComparer;
public SequenceComparer()
{
this.itemComparer = EqualityComparer<T>.Default;
}
public SequenceComparer(IEqualityComparer<T> itemComparer)
{
this.itemComparer = itemComparer;
}
public bool Equals(IEnumerable<T> x, IEnumerable<T> y)
{
if (object.Equals(x, y))
return true;
if (x == null || y == null)
return false;
return x.SequenceEqual(y, itemComparer);
}
public int GetHashCode(IEnumerable<T> obj)
{
if (obj == null)
return -1;
int i = 0;
return obj.Aggregate(0, (x, y) => x ^ new { Index = i++, ItemHash = itemComparer.GetHashCode(y) }.GetHashCode());
}
}
公共类SequenceComparer:IEqualityComparer
{
IEqualityComparer项目比较器;
公共序列比较器()
{
this.itemComparer=EqualityComparer.Default;
}
公共SequenceComparer(IEqualityComparer itemComparer)
{
this.itemComparer=itemComparer;
}
公共布尔等于(IEnumerable x,IEnumerable y)
{
if(对象等于(x,y))
返回true;
如果(x==null | | y==null)
返回false;
返回x.SequenceEqual(y,itemComparer);
}
public int GetHashCode(IEnumerable obj)
{
if(obj==null)
返回-1;
int i=0;
返回obj.Aggregate(0,(x,y)=>x^new{Index=i++,ItemHash=itemComparer.GetHashCode(y)}.GetHashCode());
}
}
更新:我想到了使用匿名类型从孔乐的答案中生成一个更好的散列,我将其修改并使其在我的类中工作。构建自定义的EqualityComparer
:
编辑:
将索引包括到方法GetHashCode
中,以确保不同的顺序不相等这个简单的程序可以满足您的需要:
using System;
using System.Collections.Generic;
using System.Linq;
namespace ConsoleApplication6
{
class Program
{
static void Main(string[] args)
{
List<List<int>> lists = new List<List<int>>();
lists.Add(new List<int> { 1, 2, 3 });
lists.Add(new List<int> { 1, 2, 3 });
lists.Add(new List<int> { 9, 10, 11 });
lists.Add(new List<int> { 1, 2, 3 });
var distinct = lists.Select(x => new HashSet<int>(x))
.Distinct(HashSet<int>.CreateSetComparer());
foreach (var list in distinct)
{
foreach (var v in list)
{
Console.Write(v + " ");
}
Console.WriteLine();
}
}
}
}
使用系统;
使用System.Collections.Generic;
使用System.Linq;
命名空间控制台应用程序6
{
班级计划
{
静态void Main(字符串[]参数)
{
列表=新列表();
添加(新列表{1,2,3});
添加(新列表{1,2,3});
增加(新名单{9、10、11});
添加(新列表{1,2,3});
var distinct=lists.Select(x=>newhashset(x))
.Distinct(HashSet.CreateSetComparer());
foreach(不同格式的变量列表)
{
foreach(列表中的var v)
{
控制台。写入(v+“”);
}
Console.WriteLine();
}
}
}
}
对于小型数据集,比较器可能很有用,但如果您有1000个或更多列表>,则尝试将它们全部进行比较可能会花费很长时间
我建议您改为使用您的数据来构建一个独特的树。树的构建速度会快得多,完成后,您可以随时将您的数据带回旧的数据结构。我想比较@Leniel Macaferi和@L.B答案的性能,因为我不确定哪一个更有效,或者差异将是显著的。结果表明,差异非常显著:
Method 1: 00:00:00.0976649 @Leniel Macaferi
Method 2: 00:00:32.0961650 @L.B
以下是我用来对它们进行基准测试的代码:
public static void Main(string[] args)
{
var list = new List<List<int>> {new List<int> {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<int> {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<int> {1, 2, 3, 1, 2, 3, 1, 2, 3, 1, 2, 3, 1, 2, 3, 1, 2, 3, 9, 10, 11, 1}, new List<int> {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<int> {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<int> {1, 2, 3, 1, 2, 3, 1, 2, 3, 1, 2, 3, 1, 2, 3, 1, 2, 3, 9, 10, 11}, new List<int> {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<int> {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<int> {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<int>(x)).Distinct(HashSet<int>.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();
}
publicstaticvoidmain(字符串[]args)
{
新列表{新列表{新列表{1,2,2,3,3,1,1,2,2,2,2,3,1,3,1,3,1,1,3,1,1,1,1,1,2,2,3,3,3,3,3,3,3,3,3,1,1,1,1,2,3,3,3,1,1,1,1,1,1,1,1,1,2,1,1,2,1,1,2,1,1,2,1,2,1,1,2,1,2,1,2,1,2,1,1,2,1,2,1,1,2,1,1,1,2,1,2,1,2,1,1,2,2,1,1,1,2,2,1,2,1,2,1,2,1,2,1,1,1,1,2,1,1,新列表1、1、2、2、2、3、3、3、3、3、3、3、1、3、3、1、1、2、2、3、1、3、3、3、1、3、1、3、3、3、3、3、1、3、3、3、3、3、3、3、3、3、3、3、3、3、3、3、3、3、3、1、3、1、1、3、1、1、3、1、1、2、2、3、2、3、3、3、3、1、1、2、3、2、3、3、2、3、3、3、3、3、1、3、3、3、1、3、3、3、3、1、1、3、1、3、3、3、3、3、3、1、3、3、3、1、3、3、3、3、3、3、3、1、3、3、1、3、3、1、3 10,11},新列表1、1、2、2、2、3、3、3、3、3、3、1、3、3、3、1、1、2、2、3、3、1、2、3、3、3、3、3、3、3、3、3、3、1、3、3、3、3、3、3、3、3、3、3、3、3、3、3、3、3、1、1、3、1、3、1、1、1、2、2、1、2、2、2、2、3、3、3、1、1、1、3、1、1、1、2、1、3、1、1、1、3、1、1、1、1、1、2、2、1、1、2、1、1、1、2、1、2、2、2、2、1、1、2、2、1、1、2、2、2、3、2、2、3、1、1、1、1、1、1、2}};
var sw1=新秒表();
sw1.Start();
对于(变量i=0;i<1\u 000\u 000;i++)
{
var distinct=list.Select(x=>newhashset(x)).distinct(HashSet.CreateSetComparer());
}
sw1.Stop();
WriteLine($“方法1:{sw1.appeased}”);
var sw2=新秒表();
sw2.Start();
对于(变量i=0;i<1\u 000\u 000;i++)
{
var distinct=list.GroupBy(a=>string.Join(“,”,a)).Select(a=>a.First()).ToList();
}
sw2.Stop();
WriteLine($“方法2:{sw2.appeased}”);
Console.ReadKey();
}
请注意,列表中的T必须实现IComparable。如果T是自定义类型,您必须自己实现。@MichaelSallmen我展示了一个实现,它可以选择使用IEqualityComparer
来指定如何比较T
对象。不过,这一点很好。(未定义适当比较接口的类型上的默认相等比较器将仅检查引用相等)@Servy yes,的确如此。不过,这只是一个示例实现。编写一个好的实现并非易事(例如,请参阅Coung Le的更好的实现,它仍然存在问题)。也许在XORing之前将每个项目的哈希值乘以下一个较大的素数会更好?@TimS。我会留下一个//来生成哈希值,而不是把你所拥有的放进去;至少这样读者会知道他们需要自己找到一个好的算法,而不会认为这是好的。@Servy我已经用一个很好的实现。否则,我同意你的看法。是{1,2,3
var finalList = lists.GroupBy(x => String.Join(",", x))
.Select(x => x.First().ToList())
.ToList();
Method 1: 00:00:00.0976649 @Leniel Macaferi
Method 2: 00:00:32.0961650 @L.B
public static void Main(string[] args)
{
var list = new List<List<int>> {new List<int> {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<int> {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<int> {1, 2, 3, 1, 2, 3, 1, 2, 3, 1, 2, 3, 1, 2, 3, 1, 2, 3, 9, 10, 11, 1}, new List<int> {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<int> {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<int> {1, 2, 3, 1, 2, 3, 1, 2, 3, 1, 2, 3, 1, 2, 3, 1, 2, 3, 9, 10, 11}, new List<int> {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<int> {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<int> {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<int>(x)).Distinct(HashSet<int>.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();
}