检查一个IEnumerable是否包含另一个IEnumerable的所有元素

Bra*_*rie 96 .net c# linq ienumerable

在比较两个集合中每个元素的字段/属性时,确定一个IEnumerable是否包含另一个IEnumerable的所有元素的最快方法是什么?


public class Item
{
    public string Value;

    public Item(string value)
    {
        Value = value;
    }
}

//example usage

Item[] List1 = {new Item("1"),new Item("a")};
Item[] List2 = {new Item("a"),new Item("b"),new Item("c"),new Item("1")};

bool Contains(IEnumerable<Item> list1, IEnumerable<Item>, list2)
{
    var list1Values = list1.Select(item => item.Value);
    var list2Values = list2.Select(item => item.Value);

    return //are ALL of list1Values in list2Values?
}

Contains(List1,List2) // should return true
Contains(List2,List1) // should return false
Run Code Online (Sandbox Code Playgroud)

Ken*_*art 126

除非您跟踪并维护一些确定一个集合中的所有值是否包含在另一个集合中的状态,否则没有"快速方法".如果你只需要IEnumerable<T>反对,我会用Intersect.

var allOfList1IsInList2 = list1.Intersect(list2).Count() == list1.Count();
Run Code Online (Sandbox Code Playgroud)

这个的表现应该是非常合理的,因为Intersect()只会枚举每个列表一次.此外,Count()如果底层类型是一个ICollection<T>而不仅仅是一个,那么第二次调用将是最佳的IEnumerable<T>.

  • 如果列表中存在重复项,则此操作不起作用。例如,比较 441 和 414 的字符数组会返回 41,因此计数失败。 (5认同)

小智 54

您还可以使用Except从第一个列表中删除第二个列表中存在的所有值,然后检查是否已删除所有值:

var allOfList1IsInList2 = !list1.Except(list2).Any();
Run Code Online (Sandbox Code Playgroud)

这种方法的优点是不需要两次调用Count().

  • 这适用于list1具有重复值的情况.接受的答案没有. (13认同)

Joh*_*n K 20

C#3.5+

使用Enumerable.All<TSource>以确定是否所有列表2项都包含在列表1:

bool hasAll = list2Uris.All(itm2 => list1Uris.Contains(itm2));
Run Code Online (Sandbox Code Playgroud)

当list1包含的内容甚至超过list2的所有项时,这也将起作用.

  • 哎呀在`All()`调用中对`Contains()`调用的性能影响. (9认同)
  • **速记:**`bool hasAll = list2Uris.All(list1Uris.Contains);` (2认同)