在许多列表中选择一些看起来像列表的列表

  • 本文关键字:列表 看起来 选择 许多 c#
  • 更新时间 :
  • 英文 :


很抱歉,如果标题让你困惑了。
从列表的列表中选择一些列表

我想在许多列表中选择一些看起来像列表的列表


示例:
// 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的答案很好,运行性能很好。

澄清后的更新

前提是,用ExceptTaken去掉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();

最新更新