linq 检查两个列表是否相等

c9qzyr3d  于 2023-06-03  发布在  其他
关注(0)|答案(4)|浏览(509)

我有一个类如下:

public class Tag {
    public Int32 Id { get; set; }
    public String Name { get; set; }
}

我有两个标签列表:

List<Tag> tags1;
List<Tag> tags2;

我使用LINQ的select来获取每个标签列表的Id。然后:

List<Int32> ids1 = new List<Int32> { 1, 2, 3, 4 };
List<Int32> ids2 = new List<Int32> { 1, 2, 3, 4 };
List<Int32> ids3 = new List<Int32> { 2, 1, 3, 4 };
List<Int32> ids4 = new List<Int32> { 1, 2, 3, 5 };
List<Int32> ids5 = new List<Int32> { 1, 1, 3, 4 };

ids1应该等于ids2和ids3…两者的数字相同。
ids1不应等于ids4和ids5…
我尝试了以下操作:

var a = ints1.Equals(ints2);
var b = ints1.Equals(ints3);

但都给予假的。
检查标签列表是否相等的最快方法是什么?

更新

我正在寻找标签与书中标签完全相同的帖子。

IRepository repository = new Repository(new Context());

IList<Tags> tags = new List<Tag> { new Tag { Id = 1 }, new Tag { Id = 2 } };

Book book = new Book { Tags = new List<Tag> { new Tag { Id = 1 }, new Tag { Id = 2 } } };

var posts = repository
  .Include<Post>(x => x.Tags)
  .Where(x => new HashSet<Int32>(tags.Select(y => y.Id)).SetEquals(book.Tags.Select(y => y.Id)))
  .ToList();

我正在使用Entity Framework,得到错误:
mscorlib.dll中发生类型为“System.NotSupportedException”的异常,但未在用户代码中处理
其他信息:LINQ to Entities无法识别方法“Boolean SetEquals(System.Collections.Generic.IEnumerable`1[System.Int32])”方法,并且此方法无法转换为存储表达式。
我该怎么解决这个问题?

vkc1a9a2

vkc1a9a21#

使用SequenceEqual检查序列相等性,因为Equals方法检查 * 引用相等性 *。

var a = ints1.SequenceEqual(ints2);

或者如果你不关心元素的顺序,使用Enumerable.All方法:

var a = ints1.All(ints2.Contains);

第二个版本还需要对Count进行另一次检查,因为即使ints2包含的元素比ints1多,它也会返回true。所以更正确的版本应该是这样的:

var a = ints1.All(ints2.Contains) && ints1.Count == ints2.Count;

为了检查 * 不等式 *,只需反转All方法的结果:

var a = !ints1.All(ints2.Contains)
ykejflvf

ykejflvf2#

List<T>相等性不会逐个元素检查它们。你可以使用LINQ's SequenceEqual method来实现:

var a = ints1.SequenceEqual(ints2);

要忽略顺序,请使用SetEquals

var a = new HashSet<int>(ints1).SetEquals(ints2);

这应该可以工作,因为您正在比较不包含重复项的ID序列。如果是这样的话,你需要考虑到重复,在线性时间内完成的方法是组成一个基于哈希的计数字典,为第一个序列的每个元素加一个,为第二个序列的每个元素减一个,并检查结果计数是否全为零:

var counts = ints1
    .GroupBy(v => v)
    .ToDictionary(g => g.Key, g => g.Count());
var ok = true;
foreach (var n in ints2) {
    int c;
    if (counts.TryGetValue(n, out c)) {
        counts[n] = c-1;
    } else {
        ok = false;
        break;
    }
}
var res = ok && counts.Values.All(c => c == 0);

最后,如果您可以使用O(N*LogN)解决方案,则可以对两个序列进行排序,并使用SequenceEqual比较它们是否相等。

kqqjbcuj

kqqjbcuj3#

Enumerable.SequenceEqual(FirstList.OrderBy(fElement => fElement), 
                         SecondList.OrderBy(sElement => sElement))
wgeznvg7

wgeznvg74#

如果你想要相等的*值或相同序列中的对象,那么这些扩展可能对你有用: (相等的意思是值相等)*
对于包含值类型的列表:

public static bool ContainsEqualValuesInSameSequence<T>(this IReadOnlyList<T> left, IReadOnlyList<T> right)
    // restricted to value types since we do not do any null checking on the values.
    where T : struct, IEquatable<T>
{
    if (ReferenceEquals(left, right))
    {
        return true;
    }

    if (left == null || right == null)
    {
        return false;
    }

    if (left.Count != right.Count)
    {
        return false;
    }

    for (var i = 0; i < left.Count; i += 1)
    {
        var leftItem = left[i];
        var rightItem = right[i];

        if (leftItem.Equals(rightItem) == false)
        {
            return false;
        }
    }

    return true;
}

对于包含引用类型的列表:

public static bool ContainsEqualObjectsInSameSequence<T>(this IReadOnlyList<T> left, IReadOnlyList<T> right)
    // restricted to reference types since we do null checking on the objects.
    where T : class, IEquatable<T>
{
    if (ReferenceEquals(left, right))
    {
        return true;
    }

    if (left == null || right == null)
    {
        return false;
    }

    if (left.Count != right.Count)
    {
        return false;
    }

    for (var i = 0; i < left.Count; i += 1)
    {
        var leftItem = left[i];
        var rightItem = right[i];

        if (leftItem == null)
        {
            if (rightItem != null)
            {
                return false;
            }
        }
        else if (leftItem.Equals(rightItem) == false)
        {
            return false;
        }
    }

    return true;
}

相关问题