Check if a list contains all of another lists items when comparing on one property
Asked Answered
V

3

12

I am learning Linq and I have two object lists. I want to compare one of these lists against the other to see if all of one of the properties of the objects within it can be matched to those in the other list. So, I provide code for that but I want to change it to Linq expressions.

var list1 = new List<Product>
{
    new Product{SupplierId = 1,ProductName = "Name1"},
    new Product{SupplierId = 2,ProductName = "Name2"},
    new Product{SupplierId = 3,ProductName = "Name3"},
    new Product{SupplierId = 4,ProductName = "Name4"}
};

var list2 = new List<Product>
{
    new Product {SupplierId = 1,ProductName = "Name5"},
    new Product {SupplierId = 4,ProductName = "Name6"}
};

private static bool CheckLists(List<Product> list1, List<Product> list2)
{
    foreach (var product2 in list2)
    {
        bool result = false;
        foreach (var product in list1)
        {
            if (product.SupplierId == product2.SupplierId)
            {
                result = true;
                break;
            }
        }
        if (!result)
        {
            return false;
        }
    }
    return true;
}

How can I do it using LINQ?

Vardar answered 21/11, 2017 at 19:26 Comment(3)
Is there some reason you aren't using Contains?Foumart
@Foumart For using Contains he should override EqualsWampumpeag
For extra clarity, for anyone reading this subsequently, the check being done is whether all the items in list2 can be found in list1.Similarity
F
36
bool existsCheck = list1.All(x => list2.Any(y => x.SupplierId == y.SupplierId));

would tell you if all of list1's items are in list2.

Fenestra answered 21/11, 2017 at 19:32 Comment(2)
The most readable solution. Why does everyone complicate things?Bearnard
This solution really makes sense. I'd recommend this one as my answer.Dissertation
J
8

You want to check whether there are any IDs in list1 that aren't in list2:

if (list1.Select(p => p.SupplierId).Except(list2.Select(p => p.SupplierId)).Any())
Jackfruit answered 21/11, 2017 at 19:28 Comment(3)
I think you have list1 and list2 backwards.Foumart
@Jackfruit I'm not sure this is correct; if you change '4' in List2 to '5' won't this will still return true whereas the original code sample would return false?Similarity
Like NetMage says he's checking if there are any IDs in List2 which aren't in List1, not the other way round, so I think these need reversing and a '!' addingSimilarity
F
0

To see that list1 contains all of list2, check if Any of list1 matches All of list2:

private static bool CheckLists(List<Product> list1, List<Product> list2) => list2.All(l2p => list1.Any(l1p => l1p.SupplierId == l2p.SupplierId));

However, I would probably write an generic extension method:

public static class Ext {
    static public bool ContainsAll<T, TKey>(this List<T> containingList, List<T> containee, Func<T, TKey> key) {
        var HSContainingList = new HashSet<TKey>(containingList.Select(key));
        return containee.All(l2p => HSContainingList.Contains(key(l2p)));
    }
    static public bool ContainsAll<T>(this List<T> containingList, List<T> containee) => containingList.ContainsAll(containee, item => item);
}

Then you can call it like:

var ans = list1.ContainsAll(list2, p => p.SupplierId);
Foumart answered 21/11, 2017 at 19:38 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.