很抱歉,如果标题让你困惑了。
从列表的列表中选择一些列表
我想在许多列表中选择一些看起来像列表的列表
示例:
// data source
List<List<int>> sources = new List<List<int>>();
sources.Add(new List<int>(){1, 2, 3, 4});
sources.Add(new List<int>(){1, 2, 3, 4, 5});
sources.Add(new List<int>(){1, 2, 3, 4, 5, 6});
sources.Add(new List<int>(){1, 2, 99, 3, 4, 5, 6});
sources.Add(new List<int>(){1, 3, 99, 2, 4, 5});
sources.Add(new List<int>(){5, 4, 3, 2, 1});
sources.Add(new List<int>(){1, 2, 4, 5, 6});
sources.Add(new List<int>(){1, 2, 69, 3, 4, 5});
// the list that we want to find lists similar to this
List<int> current = new List<int>() {1, 2, 3, 4, 5};
列表中包含不重要的元素,可以忽略。更新!如果它的元素没有出现在当前中:
List<int> flexible = new List<int>() {99, 66, 123123, 2};// <= updated!
我要写的函数:
void FilterA(List<int> current, List<List<int>> sources, List<int> flexible) {}
如何使FilterA
输出这些列表(所选列表)) ?不需要打印功能
Lists chosen
1 2 3 4 5 // exactly the same !
1 2 3 4 5 6 // same first 5 elements, the rests are not important
1 2 99 3 4 5 6 // 99 is in flexible list, after ignored that is 1 2 3 4 5 6
// Updated! Ignore 99 because it is not in list current
Lists ignored
1 2 3 4 // missing 5 in current
1 3 99 2 4 5 // 99 is in flexible list, after ignored that is 1 3 2 4 5
5 4 3 2 1 // wrong order
1 2 4 5 6 // missing 3 in current
1 2 69 3 4 5 // 69 is not in flexible list
非常感谢!
—已更新—
如果列表flexible
中的元素出现在列表current
中,它们不能被排除。
@Sweeper的回答不错。
p/s:在current
中没有flexible
元素出现的情况下,@TheGeneral的答案很好,运行性能很好。
澄清后的更新
前提是,用Except
、Take
n去掉flexible,然后与SequenceEqual
比较。
注:三种方法的线性时间复杂度均为O(n)
var results = sources.Where(x =>
x.Except(flexible)
.Take(current.Count)
.SequenceEqual(current));
1, 2, 3, 4, 5
1, 2, 3, 4, 5, 6
1, 2, 99, 3, 4, 5, 6
完整的演示在这里
额外资源
可点数的。除了
产生两个序列的集合差。
可点数的。把
返回a开头指定数目的连续元素序列。
可点数的。SequenceEqual
根据等式判断两个序列是否相等比较器。
您应该编写一个方法来确定是否应该选择一个列表(candidate
):
public static bool ShouldChoose(List<int> candidate, List<int> current, List<int> flexible) {
int candidateIndex = 0;
foreach (int element in current) {
if (candidateIndex >= candidate.Count) {
return false;
}
// this loop looks for the next index in "candidate" where "element" matches
// ignoring the elements in "flexible"
while (candidate[candidateIndex] != element) {
if (!flexible.Contains(candidate[candidateIndex])) {
return false;
}
candidateIndex++;
}
candidateIndex++;
}
return true;
}
然后你可以做一个Where
过滤器:
var chosenLists = sources.Where(x => ShouldChoose(x, current, flexible)).ToList();
foreach (var list in chosenLists) {
Console.WriteLine(string.Join(", ", list));
}
这个适合我:
var results =
sources
.Where(source => source.Except(flexible).Count() >= current.Count())
.Where(source => source.Except(flexible).Zip(current, (s, c) => s == c).All(x => x))
.ToList();