c#在2个/多个列表中查找项目

时间:2012-01-03 17:30:40

标签: c# generics

我有一个常见的问题,即我希望将元素放在2个(或更多)列表中。但有时我想找到一个可能在其中一个列表中的元素。现在有不止一种方法可以做到这一点,例如使用linq或追加,但似乎都涉及不必要地创建包含单独列表的所有元素的额外列表,因此浪费处理时间。

所以我正在考虑创建我自己的通用FindinLists类,它将采用2个列表,因为它的构造函数参数将提供Find()和Exists()方法。如果在第一个列表中找不到该项,则查找和存在方法只需要搜索第二个或后续列表。 FindInLists类可以在(无setter)属性的getter中实例化。 FindInLists类的第二个构造函数可以将列表数组作为其参数。

这有用还是已经有办法搜索多个列表而不会产生超级列表创建的浪费开销?

4 个答案:

答案 0 :(得分:3)

Linq凭借FirstOrDefault method已拥有此功能。它使用延迟执行,因此将从任何输入流式传输,并在找到匹配元素时将返回短路。

var matched = list1.Concat(list2).FirstOrDefault(e => element.Equals(e));

更新

BaseType matched = list1.Concat(list2).Concat(list3).FirstOrDefault(e => element.Equals(e));

答案 1 :(得分:3)

您可以使用LINQ Concat功能。

var query = list1.Concat(list2).Where(x => x.Category=="my category");

答案 2 :(得分:2)

我相信IEnumerable<T>.Concat()就是你所需要的。它不会创建额外的列表,它只在查询时迭代给定的一对集合

Concat()使用延迟执行,所以在它被调用时它只创建一个迭代器,它存储对两个连接的IEnumebles的引用。在枚举结果集合时,它首先迭代,然后遍历第二个。 这是迭代器的反编译代码 - 那里没有火箭科学:

private static IEnumerable<TSource> ConcatIterator<TSource>(IEnumerable<TSource> first, IEnumerable<TSource> second)
{
    foreach (TSource iteratorVariable0 in first)
    {
        yield return iteratorVariable0;
    }
    foreach (TSource iteratorVariable1 in second)
    {
        yield return iteratorVariable1;
    }
}

在查看Concat()的文档时,我偶然发现了另一个我不知道的替代方案 - SelectMany。给定一组集合,它允许您一次性处理所有父集合的子集:

IEnumerable<string> concatenated = new[] { firstColl, secondColl }
    .SelectMany(item => item);

答案 3 :(得分:1)

您可能只需创建一个列表列表,然后在该列表中使用linq。它仍在创建一个新列表,但它是一个引用列表,而不是复制所有列表的内容。

List<string> a = new List<string>{"apple", "aardvark"};
List<string> b = new List<string>{"banana", "bananananana", "bat"};
List<string> c = new List<string>{"cat", "canary"};
List<string> d = new List<string>{"dog", "decision"};

List<List<string>> super = new List<List<string>> {a,b,c,d};

super.Any(x=>x.Contains("apple"));

Any调用应该在第一个列表返回true后返回,因此如果在以前的列表中找到它,请求将不会处理以后的列表。

编辑:写完这篇文章之后,我更喜欢使用Concat的答案,但如果你想要的东西可能更美观,我会把它留在这里作为替代。 ; - )