【问题标题】:Using SequenceEqual and then returning which elements don't match使用 SequenceEqual 然后返回不匹配的元素
【发布时间】:2026-02-18 00:30:01
【问题描述】:

我有两个List<string>,我正在使用SequenceEqual 方法来确定它们是否匹配。

我现在需要获取List<int>, string, IEnumerable, 任何失败元素的索引。

有什么简单的方法吗?

谢谢

【问题讨论】:

  • 简单的循环不适合你吗?
  • 你想要“失败的元素的索引”是什么意思? SequenceEqual 返回 bool 表示“这些序列的元素相同”。 表征差异有许多不同的方式 - 你想要什么?

标签: c# .net linq c#-4.0 .net-4.0


【解决方案1】:

我想你想要:

List<string> list1 = ...
List<string> list2 = ...

var differentIndices = list1.Zip(list2, (item1, item2) => item1 == item2)
                            .Select((match, index) => new { Match = match, Index = index })
                            .Where(a => !a.Match)
                            .Select(a => a.Index);

请注意,如果其中一个列表比另一个长,则不会考虑超出较小列表长度的项目。

【讨论】:

  • 酷,我不知道Zip 方法。看起来对这样的事情很有用。是否有类似的方法包含两个序列中的所有项目?没有它似乎不完整。
  • @Scott:那么除了较小列表的长度之外,您还想包含较大列表的所有索引吗?
  • 不,我只是好奇是否有一种方法与Zip 的作用相同,但会扩展到更大序列的长度而不是更小的序列。它可以传入default (T) 或其他东西。但它听起来并不像它已经存在。
  • @Scott:不,从 .NET 4 开始,标准 LINQ to Objects 中没有。不过,您可以自己编写一个。
  • @Scott:你有什么理由这么说? Zip 是函数式编程的一个术语,我相信。并且截断到较短序列的长度与其他语言中的运算符实现一致,例如Python。
【解决方案2】:

您可以使用 LINQ:

var firstFiltered = firstList.Except(secondList);
var secondFiltered = secondList.Except(firstList);

var bothFiltered = firstFiltered.Concat(secondFiltered);

注意:我确信有更有效的方法来做到这一点......

【讨论】:

    【解决方案3】:

    听起来你想要“交叉点”的反面。交集是两个列表中都存在的项目...并且您希望两个列表中存在的项目。
    这是一个简单的方法:

    var items = first.Union(second).Except(first.Intersect(second));
    

    例子:

    var first = new[]{"A","B","C","D"};
    var second = new[]{"C","D","E","F"};
    
    var items = first.Union(second).Except(first.Intersect(second));
    // Result: "A","B", "E","F"
    

    【讨论】:

      【解决方案4】:

      假设您的列表是 list1list2

       IEnumerable<string> setDifferent =
                list1.Except(list2);
      

      上面将为您提供 list1 中所有不在 list2 中的元素

      【讨论】:

      • 谢谢。这会给我字符串或索引吗?是否可以只获取索引?
      • 它会给你不匹配的字符串列表。
      【解决方案5】:

      使用它。

      var diff = l1.Except(l2);  
      Array.ForEach(diff.ToArray(), r => Console.WriteLine(r));
      

      【讨论】:

        【解决方案6】:

        如果列表可以是不同的长度,你可以这样做:

        IList<string> first = new List<string> { "A", "B", "C", "D", "E", "F" };
        IList<string> second = new List<string> { "A", "Z", "C", "D", "Y" };
        
        IList<string> longer = first;
        IList<string> shorter = second;
        
        IEnumerable<int> differentIndices = longer.Select((s, i) => i > shorter.Count - 1 || !s.Equals(shorter[i]) ? i : -1).Where(n => n >= 0);
        
        Console.WriteLine(string.Join(", ", differentIndices));
        

        这实际上是一条线。这个例子的结果是"1, 4, 5"

        关键是Select将匹配的索引映射到-1,然后这些被Where过滤掉。

        【讨论】: