【问题标题】:How to get the duplicate key in a ToDictionary cast? [duplicate]如何在 ToDictionary 演员表中获取重复键? [复制]
【发布时间】:2014-05-16 01:50:20
【问题描述】:

我必须在我的应用程序中将列表转换为字典,但我收到一个错误消息,提示 “已添加具有相同键的项目”。但它是一个列表,然后5k 个对象,我需要查看哪些对象具有相同的键。有没有办法做到这一点? 在消息异常中我无法得到它,所以我认为我可以使用 foreach 或其他东西来做到这一点。 有什么建议么? 谢谢!

编辑:

   var targetDictionary = targetCollection.ToDictionary(k => k.Key);

这个目标集合是一个通用的 IEnumerable,我从第三方数据库获得的密钥,所以我无权访问它。解决方案是找到有问题的对象并告诉供应商。

【问题讨论】:

  • 您的清单中有哪些项目?您目前如何尝试将列表变成字典?
  • 你可以在ToDictionary 之前使用Distinct 之类的东西来确保你没有重复,但是你的问题没有提供足够的信息来解决问题。
  • @DanielBrückner 我制作并编辑了。谢谢
  • 所以你不需要字典,你只想知道有重复键的项目,对吧?

标签: c# .net collections


【解决方案1】:

您可以使用 LINQ 来捕获重复项。然后,您可以根据需要处理它们。

创建一个不包含重复项的字典

var duplicates = myList.GroupBy(x => x.SomeKey).Where(x => x.Count() > 1);

var dictionaryWithoutDups = myList
    .Except(duplicates.SelectMany(x => x))
    .ToDictionary(x => x.SomeKey);

创建一个只包含每个重复项中的第一个的字典

var groups = myList.GroupBy(x => x.SomeKey);

var dictionaryWithFirsts = groups.Select(x => x.First()).ToDictionary(x => x.SomeKey);

【讨论】:

    【解决方案2】:
    var badGroups = collection.GroupBy(item => item.Key)
                              .Where(group => group.Count() > 1);
    
    foreach (var badGroup in badGroups)
    {
       Console.WriteLine("The key {0} appears {1} times.", badGroup.Key, badGroup.Count());
    
       forach (var badItem in badGroup)
       {
          Console.WriteLine(badItem);
       }
    }
    
    var goodItems = collection.GroupBy(item => item.Key)
                              .Where(group => group.Count() == 1)
                              .SelectMany(group => group);
    
    foreach (var goodItem in goodItems)
    {
       Console.WriteLine("The key {0} appears exactly once.", goodItem.Key);
    }
    
    var dictionary = goodItems.ToDictionary(item => item.Key);
    

    【讨论】:

      【解决方案3】:

      如果您想保留重复项,您可以改用.ToLookup。它创建了一个ILookup<TKey, TValue>,它基本上是一个只读的Dictionary<TKey, IEnumerable<TValue>>,其中重复项存储为集合中的“值”。

      【讨论】:

        【解决方案4】:

        如果你只是在寻找副本

        HashSet<string> hs = new HashSet<string>();   
        foreach(string s in myList) if(!hs.Add(s)) Debug.WriteLine("dup: " + s);
        

        或者如果你想处理,你可以将 hs 更改为 Dictionary

        Dictionary<string, myclass> dl = new Dictionary<string, myclass>();    
        foreach(string s in myList)
        {
           if(dl.ContainsKey(s)) 
           {
              Debug.WriteLine("dup: " + s);
           }
           else 
           {
              dl.Add(s, null);
           }
        }
        

        我看到您接受了 LINQ 答案,但 LINQ 不会胜任此操作。

        【讨论】:

        • @NathanA 是的,我自己查了一下
        • 您可以将其简化为if (!hs.Add(s)) { Debug.WriteLine("dup: " + s); },因为Add 会告诉您该项目是否已经存在。
        • @DanielBrückner 同意,但 Dictionary.Add 不能这样工作,我希望代码可以双向使用。
        猜你喜欢
        • 2011-07-31
        • 1970-01-01
        • 2020-03-08
        • 1970-01-01
        • 1970-01-01
        • 2021-09-04
        • 2011-07-06
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多