120

I have the following method:

namespace ListHelper { public class ListHelper<T> { public static bool ContainsAllItems(List<T> a, List<T> b) { return b.TrueForAll(delegate(T t) { return a.Contains(t); }); } } } 

The purpose of which is to determine if a List contains all the elements of another list. It would appear to me that something like this would be built into .NET already, is that the case and am I duplicating functionality?

Edit: My apologies for not stating up front that I'm using this code on Mono version 2.4.2.

2
  • See also stackoverflow.com/questions/332973/… Commented Jan 5, 2016 at 16:41
  • Your algorithm is quadratic O(nm). If the lists are sorted, testing if one is a subset of another should be possible in O(n+m) time. Commented Jan 5, 2016 at 16:49

6 Answers 6

209

If you're using .NET 3.5, it's easy:

public class ListHelper<T> { public static bool ContainsAllItems(List<T> a, List<T> b) { return !b.Except(a).Any(); } } 

This checks whether there are any elements in b which aren't in a - and then inverts the result.

Note that it would be slightly more conventional to make the method generic rather than the class, and there's no reason to require List<T> instead of IEnumerable<T> - so this would probably be preferred:

public static class LinqExtras // Or whatever { public static bool ContainsAllItems<T>(this IEnumerable<T> a, IEnumerable<T> b) { return !b.Except(a).Any(); } } 
Sign up to request clarification or add additional context in comments.

9 Comments

This is untested, but wouldn't return b.Except(a).Empty(); be much more readable ?
Except that Empty() doesn't return a boolean. It returns an IEnumerable<T> with no items.
You can use LINQ to Objects in Mono, I believe... but it would be helpful if you'd state the requirements in the question to start with. Which version of Mono are you using?
If the lists are length n and m, what's the time complexity of this algorithm?
@ColonelPanic: Assuming no hash collisions, O(n+m).
|
52

Included in .NET 4: Enumerable.All

public static bool ContainsAll<T>(IEnumerable<T> source, IEnumerable<T> values) { return values.All(value => source.Contains(value)); } 

1 Comment

Enumerable.All existed before .Net 4.0, and here it's a O(N^2) operation as opposed to the one in the accepted answer.
36

Just for fun, @JonSkeet's answer as an extension method:

/// <summary> /// Does a list contain all values of another list? /// </summary> /// <remarks>Needs .NET 3.5 or greater. Source: https://stackoverflow.com/a/1520664/1037948 </remarks> /// <typeparam name="T">list value type</typeparam> /// <param name="containingList">the larger list we're checking in</param> /// <param name="lookupList">the list to look for in the containing list</param> /// <returns>true if it has everything</returns> public static bool ContainsAll<T>(this IEnumerable<T> containingList, IEnumerable<T> lookupList) { return ! lookupList.Except(containingList).Any(); } 

2 Comments

similarly: Contains Any = public static bool ContainsAny<T>(this IEnumerable<T> haystack, IEnumerable<T> needle) { return haystack.Intersect(needle).Count() > 0; }. I tried some quick performance comparisons to haystack.Count() - 1 >= haystack.Except(needle).Count(); and Intersect seemed to do better most of the time.
sheesh...use Any() not Count() > 0: public static bool ContainsAny<T>(this IEnumerable<T> haystack, IEnumerable<T> needle) { return haystack.Intersect(needle).Any(); }
4

I know a way to use LinQ methods. It's a bit weird to read, but works pretty well.

var motherList = new List<string> { "Hello", "World", "User" }; var sonList = new List<string> { "Hello", "User" }; 

You want to check if sonList is totally in motherList

To do so:

sonList.All(str => motherList.Any(word => word == str)); // Reading literally would be like "For each of all items // in sonList, test if it's in motherList 

Please check it on and see if works there too.

1 Comment

This works. But please correct the typo in this line: bool result = sonList.All(str => motherList.Any(word => word == str));
-1

You could also use another way. Override equals and use this

public bool ContainsAll(List<T> a,List<T> check) { list l = new List<T>(check); foreach(T _t in a) { if(check.Contains(t)) { check.Remove(t); if(check.Count == 0) { return true; } } return false; } } 

1 Comment

list l = new List<T>(check); I dont think this would compile and if it does, its totally unecessary as check is already a list
-1

I found most of the answers do not handle all items in list b. They handle only Distinct items in list b. If your definition of all includes duplicates:

public static bool ContainsAllItems(List<T> a, List<T> b) { int numberOfItemsRequired = b.Count(); // All items in b are required to exist in a, so they should intersect inside of a available items var bSubsetOfA = a.Where(b.Remove); // note: bSubsetOfA.Count() causes b.Remove to be performed. This means only the first execution of bSubsetOfA.Count() is correct. Subsequent runs will use a mutated and incorrect b. return bSubsetOfA.Count() == numberOfItemsRequired; } 

example test:

// inventory needs 2 cows to be true var requiredToTrade = new List<string> { "Cow", "Cow" } var inventory = new List<string> { "Cow" } Assert.False(ContainsAllItems(inventory, requiredToTrade)); 

Ways to do this without mutating b: How do I do an integer list intersection while keeping duplicates?

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.