user3210251
user3210251

Reputation: 161

Check if list contains another list. C#

EDIT, just saying the comment in the ContainsAllItem explains best.

Im sorry for asking, I know this was asked before, but I just did not get it. Ok, so I want to check If a list contains all the items in another list WITHOUT overlapping, aswell as compare the items based on the classes string, name variable(called itemname and it is public).

public class Item
{
    public string itemname;
}

So basically, have a class(lets say.. class A) with a list of items, and a function that checks takes the list of items of class A, and then compares it to another list(lets call it B), but compare it by the itemname variable not the whole item.

And most importantly could you explain in detail what it does.

So how the function/class would look as of now.

public class SomeClass
{
    public List<Item> myItems = new List<Item>();

    public bool ContainsAllItems(List<Item> B)
    {
        //Make a function that compares the to lists by itemname and only returns true if the myItems list contains ALL, items in list b.
        //Also could you explain how it works.
    }
}

Upvotes: 5

Views: 12659

Answers (4)

cecilphillip
cecilphillip

Reputation: 11596

I haven't checked the pref on this, but linq does have the Except operator.

 var x = new int[] {4,5};
 var y = new int[] {1 ,2 ,3 ,4 ,5};   

 y.Except(x).Any(); //true, not all items from y are in x
 x.Except(y).Any(); // false, all items from x are in y

Upvotes: 12

JabberwockyDecompiler
JabberwockyDecompiler

Reputation: 3390

Here is another way. I included a way to include and exclude the list comparison.

var a = new List<int> { 1, 2, 3, 4, 5 };

var b = new List<int> { 1, 2, 3 };

//Exists in list a but not in b
var c = (from i 
            in a 
         let found = b.Any(j => j == i) 
         where !found select i)
         .ToList();

//Exists in both lists
var d = (from i 
            in a  
         let found = b.Any(j => j == i) 
         where found select i)
         .ToList();

Upvotes: 0

i3arnon
i3arnon

Reputation: 116666

This isn't exactly what you asked for, but performance wise you should definitely use HashSet's IsProperSubsetOf. It can do what you want in orders of magnitude less time:

HashSet<string> a = new HashSet<string>(list1.Select(x => x.itemname));
HashSet<string> b = new HashSet<string>(list2.Select(x => x.itemname));

a.IsProperSubsetOf(b)

Explanation: HashSet uses the item's GetHashCode value and Equals method in an efficient way to compare items. That means that when it internally goes through the values in b it doesn't have to compare it to all other items in a. It uses the hash code (and an internal hash function) to check whether it already has that value or doesn't.

Because it does only a single check for every item (each check is O(1)) it's much faster than checking all items in a which would take O(n) (for each item in b that is).

Upvotes: 9

zmbq
zmbq

Reputation: 39069

B.All(itB=>myItems.Select(itA=>itA.ItemName).Contains(itB.ItemName))

Will run in O(N^2) time, but it's cool you can do that in just one rather unreadable line.

Upvotes: 5

Related Questions