LINQ查询以检测对象列表中的重复属性

Jer*_*len 4 .net c# linq linq-to-objects

我有一个对象列表.这些对象由一个自定义类组成,该类基本上包含两个字符串字段String1String2.

我需要知道的是,如果这些字符串中的任何字符串在该列表中重复.所以我想知道是否objectA.String1 == objectB.String1,或ObjectA.String2 == ObjectB.String2,或ObjectA.String1 == ObjectB.String,或ObjectA.String2 == ObjectB.String1.

另外,我想将包含重复字符串的每个对象标记为具有重复的字符串(HasDuplicate对象上有bool ).

因此,当复制检测运行时,我想简单地在列表上进行操作,如下所示:

foreach (var item in duplicationList)
    if (item.HasDuplicate)
        Console.WriteLine("Duplicate detected!");
Run Code Online (Sandbox Code Playgroud)

这似乎是用LINQ解决的一个很好的问题,但我不能为我的生活找出一个好的查询.因此我使用'good-old'foreach解决了它,但我仍然对LINQ版本感兴趣.

Win*_*ith 12

这是一个完整的代码示例,应该适合您的情况.

class A
{
    public string Foo   { get; set; }
    public string Bar   { get; set; }
    public bool HasDupe { get; set; }
}

var list = new List<A> 
          { 
              new A{ Foo="abc", Bar="xyz"}, 
              new A{ Foo="def", Bar="ghi"}, 
              new A{ Foo="123", Bar="abc"}  
          };

var dupes = list.Where(a => list
          .Except(new List<A>{a})
          .Any(x => x.Foo == a.Foo || x.Bar == a.Bar || x.Foo == a.Bar || x.Bar == a.Foo))
          .ToList();

dupes.ForEach(a => a.HasDupe = true);
Run Code Online (Sandbox Code Playgroud)

  • LINQPad是一个很好的工具,可以解决这样的问题 - 每个C#开发人员都应该有一个副本. (2认同)

Gee*_*ert 5

这应该有效:

\n\n
public class Foo\n{\n    public string Bar;\n    public string Baz;\n    public bool HasDuplicates;\n}\n\npublic static void SetHasDuplicate(IEnumerable<Foo> foos)\n{\n    var dupes = foos\n        .SelectMany(f => new[] { new { Foo = f, Str = f.Bar }, new { Foo = f, Str = f.Baz } })\n        .Distinct() // Eliminates double entries where Foo.Bar == Foo.Baz\n        .GroupBy(x => x.Str)\n        .Where(g => g.Count() > 1)\n        .SelectMany(g => g.Select(x => x.Foo))\n        .Distinct()\n        .ToList();\n\n    dupes.ForEach(d => d.HasDuplicates = true);    \n}\n
Run Code Online (Sandbox Code Playgroud)\n\n

你基本上在做的是

\n\n
    \n
  1. SelectMany :创建所有字符串及其随附的 Foo 的列表
  2. \n
  3. Distinct :删除 Foo 的同一实例的重复条目(Foo.Bar == Foo.Baz)
  4. \n
  5. GroupBy :按字符串分组
  6. \n
  7. 其中:过滤其中包含多个项目的组。这些包含重复项。
  8. \n
  9. SelectMany :从组中获取 foo。
  10. \n
  11. Distinct :从列表中删除重复出现的 foo。
  12. \n
  13. ForEach :设置 HasDuplicates 属性。
  14. \n
\n\n

与温斯顿·史密斯的解决方案相比,该解决方案的一些优点是:

\n\n
    \n
  1. 更容易扩展到更多字符串属性。假设有 5 个属性。在他的解决方案中,您必须编写 125 次比较来检查重复项(在 Any 子句中)。在此解决方案中,只需在第一个 selectmany 调用中添加属性即可。
  2. \n
  3. 对于大型列表,性能应该会好得多。温斯顿的解决方案针对列表中的每个项目迭代列表,而此解决方案仅迭代一次。(温斯顿的解决方案是 O(n\xc2\xb2),而这个是 O(n))。
  4. \n
\n