【问题标题】:Delete duplicate values from dictionary<string,List<string>> with LINQ使用 LINQ 从 dictionary<string,List<string>> 中删除重复值
【发布时间】:2016-01-08 20:59:03
【问题描述】:

我有一本带有 string 键和 List&lt;string&gt; 值的字典。我想获取每个列表的唯一值。

比如这个输入数据:

{
    "first": ["1", "2", "3", "1"],
    "second": ["2", "3", "4", "3"]
}

会返回这个:

{
    "first": ["1", "2", "3"],
    "second": ["2", "3", "4"]
}

我试过这个,但没用:

var uniq = duplidictionary.GroupBy(x => x.Value)
                          .Select(y => y.First())
                          .ToDictionary( x => x.Key, y => y.Value);

这似乎返回了我原始字典的副本,而不是返回我的预期结果。 Here is a DotNetFiddle illustrating my code not working.

如何使用 LINQ 从给定输入中获取此输出?

【问题讨论】:

    标签: c# .net linq dictionary


    【解决方案1】:

    我认为你需要这样的东西:

    Dictionary<string, List<string>> dupeLists = ...;
    
    var ret = dupeLists.ToDictionary(c => c.Key, c => c.Value.Distinct().ToList());
    

    这会将项目复制到一个新字典中,只获取值列表中每个项目的一个副本。

    所以如果dupeLists 看起来像:

    {
        "first": ["1", "2", "3", "1"],
        "second": ["2", "3", "4", "3"]
    }
    

    然后这将返回:

    {
        "first": ["1", "2", "3"],
        "second": ["2", "3", "4"]
    }
    

    与这些列表中的唯一值相比,您的代码无法正常工作,因为它正在寻找唯一的列表。因为每个列表在内存中的不同位置(您知道这一点,因为修改一个不会修改另一个),所以由您的 GroupBy 调用产生的每个组将只有一个元素长。


    最初的问题比现在清楚得多,所以我添加了几个变体以确保找到正确的答案。下面列出了这些以供后代使用,但事实证明它们不适用于这种特殊情况。


    为了更好的衡量,你said you need to“摆脱重复值”,这是模棱两可的。如果你想扔掉任何有重复的东西,

    Dictionary<string, List<string>> dupeLists = ...;
    
    var ret = dupeLists.ToDictionary(c => c.Key, c => c.Value.GroupBy(x => x)
                                                             .Where(x => x.Count() == 1)
                                                             .Select(x => x.Key)
                                                             .ToList());
    

    将返回:

    {
        "first": ["2", "3"],
        "second": ["2", "4"]
    }
    

    既然你在情绪低落的日子里抓住了我,如果你真的想返回一个不同项目的平面列表,

    Dictionary<string, List<string>> dupeLists = ...;
    
    var ret = dupeLists.SelectMany(c => c.Value).Distinct().ToList();
    

    产生:

    ["1", "2", "3", "4"]
    

    或者只是在整个字典中只出现一次的那些:

    Dictionary<string, List<string>> dupeLists = ...;
    
    var ret = dupeLists
                  .SelectMany(c => c.Value)
                  .GroupBy(c => c)
                  .Where(c => c.Count() == 1)
                  .Select(c => c.Key)
                  .ToList();
    

    这是:

    ["4"]
    

    或者只是那些只出现在任何给定列表中,而没有其他列表的:

    Dictionary<string, List<string>> dupeLists = ...;
    
    var ret = dupeLists
                  .SelectMany(c => c.Value, (kvp, Value) => new { kvp.Key, Value })
                  .GroupBy(c => c.Value)
                  .Where(c => c.Select(x => x.Key).Distinct().Count() == 1)
                  .GroupBy(c => c.Key, c => c.Value)
                  .ToDictionary(c => c.Key, c => c.ToList());
    

    如果我的未经测试的代码成立的话:

    {
        "first": ["1", "1"],
        "second": ["4"]
    }
    

    【讨论】:

    • @dotctor 不,但我确实在互联网上玩过。
    • @Matthew - 非常感谢你 - 读懂我的想法(我问了这么模糊的问题是我的错误),谢谢你回答我在这个网站上的第一个问题.. :)
    • @sst 不用担心!欢迎来到本站。这肯定需要一些时间来适应。我的哪些案例是你要找的?我会帮你编辑你的问题,以便我们重新打开它。
    • @MatthewHaugen 这种情况所以如果 dupeLists 看起来像: { "first": ["1", "2", "3", "1"], "second": ["2", "3", "4", "3"] } 然后这将返回: { "first": ["1", "2", "3"], "second": ["2", "3", "4"] }
    • @sst 太棒了,谢谢。我对你的问题做了一些相当大的修改,如果你想检查一下并确保它仍然是正确的。我还在我的末尾添加了一个简短的段落,解释了为什么你所做的事情不起作用 - 如果这没有意义,请告诉我,我认为我解释得不是很好。
    猜你喜欢
    • 1970-01-01
    • 2019-11-27
    • 1970-01-01
    • 1970-01-01
    • 2018-01-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-06-20
    相关资源
    最近更新 更多