views:

115

answers:

6

Is there an easy way, either through LINQ or Generics, to find out if elements in one List are all available in another List.

I'm currently using Intersect to check this.

For e.g.

List<string> list1; //{ 5, 4, 1, 3, 9, 8, 6, 7, 2, 0 }

List<string> list2; //{ 1, 3, 9 }

list1.Contains(list2) == true

Thanks in advance

+5  A: 

Intersect is a good way to do it. The only other reasonable way is to just brute-force it:

list2.All(x => list1.Contains(x));

Note that neither technique will work if, for example, list2 is (1 2 2) and list1 is (1 2 3) and you want that to return false. If you needed to check that, I would sort both lists and walk down them together.

mquander
+7  A: 

The Intersect method will give you all the elements that are in both lists.

E.g.

var inboth = list1.Intersect(list2);

or if you just want to know if there are any shared elements between the two

if(list1.Intersect(list2).Any()) ...
Brian Rasmussen
Thanks. One more questions: what if all elements in list2 have to be available in list1. I'm using Count. Is there a better way?
Ganesha
You could use `Except` like this `if(!list2.Except(list1).Any()) ...`
Brian Rasmussen
+1  A: 
var list1 = new [] {5, 4, 1, 3, 9, 8, 6, 7, 2};
var list2 = new[] {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,5};

var hasItems = list1.Where(x => list2.Contains(x)).Any();
Filip Ekberg
A: 

This way I'll put here is the naive aproximation, Im not sure if there's a better way

//Checks if list1 is contained in list2
public bool ContainsList( List<T> list1, List<T> list2)
{

  for ( int i = 0; i < list1.Count; i++ )
  {
     bool inside = false;

     for (int j = 0; j < list2.Count; j++){
       if  ( list1[i] == list2[j] )
         inside = true;
     }

     //found one in list1 that is not on list2!
     if ( !inside )
       return false;
  }
}

The computational cost of this answer is O(n*m), where n and m are the lengths of the lists. Is not LINQ, is not perhaps the best way, but is 100% good!

Hope it helps!

David Conde
+1  A: 

Intersect is perfect for this. If your desperate for a boolean result, you could write a custom extension method override for .Contains()

    public static bool WholeyContains<T>(this IEnumerable<T> first, IEnumerable<T> second)
    {
        return second.SequenceEqual(first.Intersect(second));
    }
Alastair Pitts
That's wrong. `first` contains `second` if the intersection is `second`, not if it's merely non-empty.
mquander
@mquander: Yep, I agree. I miss-read the question. I've updated my answer to make sure that the second list is entirely the same as the intersect.
Alastair Pitts
+1  A: 
var a = new int[]{ 1, 2, 3 };
var b = new int[] { 1, 2, 3, 4, 5 };

bool result = (from numA in a
               join numB in b
               on numA equals numB
               into joined
               select joined).Count().Equals(a.Count()); // or b.Count()
888