views:

123

answers:

3

What is the fastest way to determine if one IEnumerable contains all the elements of another IEnumerable when comparing a field/property of each element in both collections?


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>, list 2)
{
    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
+2  A: 

the Linq operator SequenceEqual would work also (but is sensitive to the enumerable's items being in the same order)

return list1Uris.SequenceEqual(list2Uris);
thekaido
+3  A: 

C# 3.5+

Using Enumerable.All<TSource> to determine if all List2 items are contained in List1:

bool hasAll = list2Uris.All(itm2 => list1Uris.Contains(itm2));

This will also work when list1 contains even more than all the items of list2.

John K
Ouch at performance implications of a `Contains()` call within an `All()` call.
Kent Boogaart
+6  A: 

There is no "fast way" to do this unless you track and maintain some state that determines whether all values in one collection are contained in another. If you only have IEnumerable<T> to work against, I would use Intersect.

var allOfList2IsInList1 = list1.Intersect(list2).Count() == list1.Count();

The performance of this should be very reasonable, since Intersect() will enumerate over each list just once. Also, the second call to Count() will be optimal if the underlying type is an ICollection<T> rather than just an IEnumerable<T>.

HTH,
Kent

Kent Boogaart
I did some tests and this method seems to run faster than the others. Thanks for the tip.
Brandon Z.