【问题标题】:How to filter a dictionary to have items with unique values?如何过滤字典以包含具有唯一值的项目?
【发布时间】:2013-01-03 12:15:58
【问题描述】:

如果您认为我在提问之前没有做足够的研究,请多多包涵

问题 刚刚遇到一个业务需求,我们必须确保字典中的值是唯一的。即,我们应该过滤一个字典,并且这种过滤的结果应该具有具有唯一值的键值对。

顺便说一句,它是一个带有字符串值和字符串键的简单字典。为了更清楚地说明,以下是示例输入和预期输出值 -
sourceDictionary 将具有如下值(只是为了表示数据,语法不正确) - { {"Item1", "Item One"}, {"Item11", "Item One"}, {"Item2", " Item Two"}, {"Item22", "Item Two"} } 对于这个输入,filteredDictionary 应该如下所示 - { {"Item1", "Item One"}, {"Item2", "Item Two"} }

我提出的可行的解决方案

    var sourceDictionary = serviceAgent.GetSampleDictionary(); // Simplified for brevity  
    var filteredDictionary =  
        sourceDictionary.GroupBy(s => s.Value)  
            .Where(group => @group.Any())  
            .Select(g => g.First())  
            .ToDictionary(kvp => kvp.Key, kvp => kvp.Value);  

问题 我是不是把逻辑太多了?或者,换句话说,有没有更简单的方法来做到这一点?

【问题讨论】:

  • @group.Any() 中的@ 是什么?这是笔误吗?
  • @Rotem "@" 允许您使用 C# 保留字。
  • 我相信这是 ReSharper 的东西......可能是因为它认为 group 是保留关键字
  • @JTA 谢谢,不知道。

标签: c# .net linq


【解决方案1】:

这一行:

.Where(group => @group.Any()) 

是不必要的,因为无论如何您都不会得到任何空组。 (也不确定“@”是干什么用的。)

除此之外,没有更简单的方法可以做到这一点。

【讨论】:

  • 我同意。 Where 子句是多余的。
【解决方案2】:

您的方法有效,但可读性不强。如果您以这种方式创建课程:

class DictionaryValueComparer<T1, T2> : IEqualityComparer<KeyValuePair<T1, T2>>
{
    public bool Equals(KeyValuePair<T1, T2> x, KeyValuePair<T1, T2> y)
    {
        return x.Value.Equals(y.Value);
    }

    public int GetHashCode(KeyValuePair<T1, T2> obj)
    {
        return obj.Value.GetHashCode();
    }
}

然后你可以将你的方法简化为:

dictionary = dictionary.Distinct(new DictionaryValueComparer<int, string>()).
    ToDictionary(p => p.Key, p => p.Value);

【讨论】:

  • 我明白你的意思。我想我应该试试这个,因为我使用了很多字典类型的查找实体。
  • @TimSchmelter 请问构造函数将如何提供帮助,因为它只比较键?
  • +1,这比GroupBy 更高效,并且在调用时更紧凑(如果您不介意将比较器类隐藏在某个地方)。
【解决方案3】:

为什么不使用 Linq 扩展方法 .Distinct()?

【讨论】:

  • 这就是我的想法,但是,无法在 Distinct 调用中使用正确的谓词
【解决方案4】:

假设它不是自定义类型(那么你需要实现IEqualityComparer&lt;YourType&gt;并传递给Distinct

var distinctDict = sourceDictionary
    .ToDictionary(kv => kv.Key, kv => kv.Value.Distinct());

Demo

var sourceDictionary=new Dictionary<string, List<string>>();
sourceDictionary.Add("A", new List<string>() { "A", "A", "B"});
sourceDictionary.Add("B", new List<string>() { "C", "D", "D" });

var distinctDict = sourceDictionary.ToDictionary(kv => kv.Key, kv => kv.Value.Distinct());
foreach(var kv in distinctDict)
    Console.WriteLine("Key:{0} Values:{1}", kv.Key, string.Join(",", kv.Value));
    // "A", "B" and "C", "D"

【讨论】:

  • 你没有误解问题吗?我认为源字典 Value 类型不是可枚举的,但 OP 不希望字典中的两个键具有相同的值。
  • 我很抱歉错过了类型信息。编辑问题以指明类型。
  • @Rotem: "我们必须确保字典中的值是唯一的。即,我们应该过滤一个字典,并且这种过滤的结果应该具有带有 的键值对唯一值。”编辑:htmm,是的,也许我以不同的方式理解了这个问题;)
  • Rotem 是对的。我基本上希望结果字典具有唯一键(显然:))和唯一值。
  • @Rotem:我不会编辑或删除它,因为其他人已经以 OP 想要的方式回答了这个问题。但它可能对遇到此标题的人有所帮助。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2020-11-27
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-11-07
  • 2011-03-26
相关资源
最近更新 更多