【问题标题】:Linq Distinct() or GroupBy() method is not working in below scenarioLinq Distinct() 或 GroupBy() 方法在以下情况下不起作用
【发布时间】:2015-07-15 16:18:58
【问题描述】:

在下面的代码中,我将字典的多个实例捆绑到一个列表中。现在我只想从列表中选择不同的值。为此,我尝试使用 distinct 和 group by,但这对我没有帮助。任何人都可以帮助我使用 linq 只选择不同的吗?

 IList<Dictionary<string, string>> lst = new List<Dictionary<string, string>>();
            Dictionary<string, string> d = new Dictionary<string, string>();
            Dictionary<string, string> d1 = new Dictionary<string, string>();
            Dictionary<string, string> d3 = new Dictionary<string, string>();
            d.Add("12345", "xyz");
            d1.Add("12345", "xyz");
            d3.Add("123456", "xyz-abc");
            lst.Add(d);
            lst.Add(d1);
            lst.Add(d3);
            var result = lst.Distinct(); //test => test.Values.ToString().Trim()); //.Select(grp => grp.First());

【问题讨论】:

  • 不同的值意味着不同的字典(这就是你目前正在尝试做的)?或者所有字典中的值(这可能更有意义)?
  • 你需要添加一个类implents IEqualityComparer&lt;TSource&gt; comparer
  • 它可以正常工作。您的字典列表中的所有三个项目都是独一无二的。
  • 实例不同但值相同,我想选择不同的相同值
  • 你会得到三个不同的字典。试试d["12345"] = "abc";,你会发现d1["12345"] 仍然是"xyz"。如果您想说如果两个(或更多)字典包含具有“相同”键和值的 KeyValuePairs,则您希望将它们视为“相同”,那么您需要在 IEqualityComparer 中实现该逻辑并使用它Distinct 的重载。

标签: c# linq


【解决方案1】:

如果您想获取所有字典的不同值,那么您需要比较每个字典中的实际元素以选择您可以使用 SelectMany 的所有元素,如下所示:

键/值对:

var result = lst.SelectMany(x=>x).Distinct();

价值观:

var result = lst.SelectMany(x=>x.Values).Distinct();

键:

var result = lst.SelectMany(x=>x.Keys).Distinct();

【讨论】:

  • 这是要比较键值对而不是值,这是你的意思吗?
  • 为字典中不同类型的对象添加示例
  • retuen 类型是键值对列表。正如我所期望的那样,这是字典列表
  • 应该这个结果。Cast>().ToList();工作吗?
  • 您希望它成为唯一键/值对的字典吗?然后,您可以使用 ToDictionary 方法将值对列表转换为字典: lst.SelectMany(x => x).Distinct().ToDictionary(x => x.Key, y => y.Value);跨度>
【解决方案2】:

您必须先从列表中选择值,然后应用Distinct()

var values = lst.SelectMany(dict => dict); // or lst.SelectMany(dict => dict.Values), I don't know what kind of values you mean
var distinctValues = values.Distinct();

【讨论】:

    【解决方案3】:

    Dictionary&lt;TKey, TValue&gt; 类不会覆盖Equals(object)GetHashCode() 方法。因此,当您使用 .Distinct()(或 GroupBy 等)时,您会获得引用相等语义。

    dd1 引用两个不同的实例(两个不同的对象)。这两个字典碰巧有相同的键和相同的对应值,但这并不能使它们成为同一个实例。因此,d != d1(作为参考)。

    您可能想要这样做:

    var result = lst.Distinct(new YourDictEqualsComparer());
    

    其中YourDictEqualsComparer 是以下类:

    // naive string-string dictionary equality comparer
    class YourDictEqualsComparer : EqualityComparer<Dictionary<string, string>>
    {
      public override bool Equals(Dictionary<string, string> x, Dictionary<string, string> y)
      {
        if (x == null || y == null)
          return Default.Equals(x, y);
    
        if (!x.Comparer.Equals(y.Comparer))
          return false;
    
        var setOfPairs = new HashSet<KeyValuePair<string, string>>(x);
        return setOfPairs.SetEquals(y);
      }
    
      public override int GetHashCode(Dictionary<string, string> obj)
      {
        if (obj == null)
          return 0;
    
        int seed = obj.Comparer.GetHashCode();
        return obj.Aggregate(seed, (hash, pair) => hash ^ pair.GetHashCode());
      }
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2021-07-18
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-05-26
      • 2023-03-18
      • 1970-01-01
      • 2023-03-08
      相关资源
      最近更新 更多