【发布时间】:2019-05-13 15:50:48
【问题描述】:
我有很多包含 id 的列表。过滤掉作为另一个列表子集的重复项和列表的最佳方法是什么?我遇到的问题是,随着列表的大小加倍,我的算法几乎呈指数级增长。
我尝试了 ContainsCombinatie 的多种变体,包括:
- 使用哈希集
- 使用排序列表
- !t2.Except(t1).Any() 如Check whether an array is a subset of another 中所建议
下面是一个带有计时器的单元测试供您试用。
public class PerformanceTestThis
{
[Test]
public void PerformanceTest2()
{
var allValues = new List<int>();
for (int i = 0; i < 2000; i++)
{
allValues.Add(i);
}
var combinaties = new List<List<int>>();
for (int i = 0; i < 10000; i++)
{
combinaties.Add(GenerateCombinatie(allValues));
}
Console.WriteLine($"Generated {combinaties.Count} combinaties");
var stopwatch = Stopwatch.StartNew();
var result = new CollectionFilter().FilterDoubles(combinaties);
stopwatch.Stop();
Console.WriteLine($"Filtered down to {result.Count} combinaties");
Console.WriteLine(stopwatch.ElapsedMilliseconds);
}
private List<int> GenerateCombinatie(List<int> allVerstrekkingen)
{
var combinatie = new List<int>();
var verstrekkingen = allVerstrekkingen.ToList();
for (int i = 0; i < Generator.GetRandomNumber(1000); i++)
{
var verstrekking = verstrekkingen[Generator.GetRandomNumber(verstrekkingen.Count)];
combinatie.Add(verstrekking);
verstrekkingen.Remove(verstrekking);
}
return combinatie.OrderBy(x => x).ToList();
}
}
public class CollectionFilter
{
public List<List<int>> FilterDoubles(List<List<int>> combinaties)
{
var withoutDoubles = new List<List<int>>();
foreach (var current in combinaties.OrderByDescending(x => x.Count))
{
if (!withoutDoubles.Any(list => ContainsCombinatie(list, current)))
{
withoutDoubles.Add(current);
}
}
return withoutDoubles;
}
private bool ContainsCombinatie(List<int> list1, List<int> list2)
{
return list2.All(list1.Contains);
}
}
【问题讨论】:
-
“双打”是指重复吗?
-
双重我的意思是另一个列表的重复或子集。正如我在“过滤掉作为另一个列表子集的双精度和列表的最佳方法是什么?”中所说的那样
-
这很令人困惑,因为
double是C#中的一种数据类型。 -
好的,我会修改问题。
-
var distinctItems = items.GroupBy(x => x.Id).Select(y => y.First()); ?