IEnumerable.Except () between different classes with a common field

Is it possible to use Except()for two lists that have two different classes, but a common field? I have collections List<User1>and List<User2>. They have different properties besides the ID column, and I want to find different records between them using this ID column. I try to use List<>.Except(), but I get this error:

Type arguments to the 'System.Linq.Enumerable.Except (System.Collections.Generic.IEnumerable, System.Collections.Generic.IEnumerable)' method cannot be taken out of use. Try explicitly specifying type arguments.

Here is what I am trying:

List<User1> list1 = List1();
List<User2> list2 = List2();
var listdiff = list1.Except(list2.Select(row => row.Id));

What am I doing wrong?

+5
source share
6

List1 User1 List2 User2.

list1.Except(list2.Select(row => row.Id))? , , var ?

User1 User2 ( ), List<User>.

:

var list2Lookup = list2.ToLookup(user => user.Id);
var listdiff = list1.Where(user => (!list2Lookup.Contains(user.Id))
+9

Except, :

// assumes that the Id property is an Int32
var tempKeys = new HashSet<int>(list2.Select(x => x.Id));
var listdiff = list1.Where(x => tempKeys.Add(x.Id));

, , :

var listdiff = list1.Except(list2, x => x.Id, y => y.Id);

// ...

public static class EnumerableExtensions
{
    public static IEnumerable<TFirst> Except<TFirst, TSecond, TKey>(
        this IEnumerable<TFirst> first,
        IEnumerable<TSecond> second,
        Func<TFirst, TKey> firstKeySelector,
        Func<TSecond, TKey> secondKeySelector)
    {
        // argument null checking etc omitted for brevity

        var keys = new HashSet<TKey>(second.Select(secondKeySelector));
        return first.Where(x => keys.Add(firstKeySelector(x)));
    }
}
+4

, List<object> # .NET 4.0: dynamic.

:

var listDiff = list1
    .AsEnumerable<object>()
    .Except(list2
        .AsEnumerable<object>()
        .Select(row => ((dynamic)row).ID));
+3

, Ids list1 list2, :

var idsInList1NotInList2 = list1.Select(user1 => user1.Id)
                                .Except(list2.Select(user2 => user2.Id));

User1, ( , User1):

// Create lookup from Id to the associated User1 object
var user1sById = list1.ToDictionary(user1 => user1.Id);

// Find Ids from the lookup that are not present for User2s from list2
// and then retrieve their associated User1s from the lookup
var user1sNotInList2 = user1sById.Keys
                                 .Except(list2.Select(user2 => user2.Id))
                                 .Select(key => user1sById[key]);

EDIT: vc74 ; .

+2
source
public static IEnumerable<TSource> Except<TSource, CSource, TKey>(this IEnumerable<TSource> source, Func<TSource, TKey> TSelector, IEnumerable<CSource> csource, Func<CSource, TKey> CSelector)
    {
        bool EqualFlag = false;
        foreach (var s in source)
        {
            EqualFlag = false;
            foreach (var c in csource)
            {
                var svalue = TSelector(s);
                var cvalue = CSelector(c);
                if (svalue != null)
                {

                    if (svalue.Equals(cvalue))
                    {
                        EqualFlag = true;
                        break;
                    }
                }
                else if (svalue == null && cvalue == null)
                {
                    EqualFlag = true;
                    break;
                }
            }
            if (EqualFlag)
                continue;
            else
            {
                yield return s;
            }
        }

    }
+2
source

Try

list1.Where(user1 => !list2.Any(user2 => user2.Id.Equal(user1.Id)));
0
source

All Articles