1

我正在使用 Enumerable.Except() 将skipSerialNumbers项从activateSerialNumbers中排除。

activatedSerialNumbers = activatedSerialNumbers
                    .Except(skipSerialNumbers, new SamWithLicenseComparer()).ToList();

SamWithLicenseComparer是:

internal class SamWithLicenseComparer : IEqualityComparer<SamWithLicense>
{
    public bool Equals(SamWithLicense x, SamWithLicense y)
    {
        if (ReferenceEquals(x, y)) 
            return true;

        if (ReferenceEquals(x, null) || ReferenceEquals(y, null))
            return false;

        if(x.Name.ToLower() != y.Name.ToLower())
            return false;
        return true;
    }

    public int GetHashCode(SamWithLicense sam)
    {
        if (ReferenceEquals(sam, null)) 
            return 0;
        return sam.Name == null ? 0 : sam.Name.ToLower().GetHashCode();
    }
}

结果我得到了意想不到的价值,因为我发现,activatedSerialNumbers中的项目会与它们自己进行比较。但逻辑是它们可能具有相同的名称,任务只是从skipSerialNumbers中删除所有项目。如何做到这一点避免额外的比较?

4

2 回答 2

3

Except是一个集合操作,因此结果将始终包含不同的值。
例如,如果你这样做{A,B,A,C}.Except({B,C}),你会得到{A},而不是{A, A}

你可以试试这个:

var skipSesialNumbersSet = new HashSet<SamWithLicense>(skipSerialNumbers, new SamWithLicenseComparer());
activatedSerialNumbers = activatedSerialNumbers.Where(x => !skipSesialNumbersSet.Contains(x)).ToList();
于 2013-08-14T16:35:23.843 回答
0

如果您还想查看重复项,则可以使用以下变体:

public static IEnumerable<TSource> ExceptWithDuplicates<TSource>(
        this IEnumerable<TSource> first,
        IEnumerable<TSource> second)
    {
        if (first == null) { throw new ArgumentNullException("first"); }
        if (second == null) { throw new ArgumentNullException("second"); }

        var secondList = second.ToList();
        return first.Where(s => !secondList.Remove(s));
    }

    public static IEnumerable<TSource> ExceptWithDuplicates<TSource>(
        this IEnumerable<TSource> first,
        IEnumerable<TSource> second,
        IEqualityComparer<TSource> comparer)
    {
        if (first == null) { throw new ArgumentNullException("first"); }
        if (second == null) { throw new ArgumentNullException("second"); }
        var comparerUsed = comparer ?? EqualityComparer<TSource>.Default;

        var secondList = second.ToList();
        foreach (var item in first)
        {
            if (secondList.Contains(item, comparerUsed))
            {
                secondList.Remove(item);
            }
            else
            {
                yield return item;
            }
        }
    }

现在你可以这样做:

var first = new [] { 1, 1, 1, 2, 2, 2, 3, 3 };
var second = new[] { 1, 2, 2, 4 };

var withoutDuplicates = first.Except(second);  // 3 
var witDuplicates = first.ExceptWithDuplicates(second);  // 1, 1, 2, 3, 3 : Note that 1 and 2 are also in the list
于 2013-08-19T07:04:10.657 回答