【问题标题】:Remove duplicate objects with lowest Num property from list从列表中删除具有最低 Num 属性的重复对象
【发布时间】:2015-02-06 05:47:51
【问题描述】:

我有一个对象列表

public class Obj
{
    public int Num {get;set;}
    public List<string> StrList {get;set;}
    ...other irrelevant properties
}

Obj 列表中的某些项目将包含相同的StrList,但会有不同的Num。我想删除列表中所有具有相似StrListObj,并保留具有最大NumNum

这是我的尝试:

objList = objList.GroupBy(x =&gt; new { x.StrList }).OrderByDescending(x =&gt; x.Select(y =&gt; y.Num)).Select(x =&gt; x.First()).ToList();

但我收到一个错误:At least one object must implement IComparable.

最好的方法是什么?

【问题讨论】:

  • 你有很多多余的东西不需要。 new { x.StrList } 应该只是 x.StrList。也无需在您的订单中进行选择。
  • Mike 对以下错误进行谷歌搜索,您在此处有 least one object must implement IComparable 作为一些结果,您可以翻阅 google.com/…
  • list.GroupBy(x =&gt; x.StrList).Select(g =&gt; g.OrderByDescending(x =&gt; x.Num).First())

标签: c# linq


【解决方案1】:
  1. 分组时没有理由将列表包装在匿名类型中;调用GroupBy时,只需将列表本身投影出来即可。

  2. List 没有覆盖EqualsGetHashCode,因此它将使用列表的引用而不是其内容来定义相等性。您需要创建一个自定义 IEqualityComparercompare the values of the sequence

  3. 您正在订购组的集合,而这些组不可比较,因此您的错误。您想订购每个组中的项目。为此,请使用Select,然后对您要投影的组进行排序(并获取结果查询中的第一个),而不是对外部集合进行排序。

【讨论】:

    【解决方案2】:

    您不能按列表分组,即使是有序列表,但您可以按通过以特定顺序连接字符串产生的单个字符串进行分组。假设有一个字符从未出现在任何字符串中(例如,'|'),您可以这样做:

    objList = objList
        .GroupBy(x => string.Join("|", x.StrList.OrderBy(s => s)))
        .Select(g => g.OrderByDescending(x => x.Num).First())
        .ToList();
    

    这个想法是通过以相同的顺序(按字典顺序升序)连接单个字符串来构造一个分组键。

    这应该适用于少量数据。如果您的列表非常大,您可以实现一个特殊的类来用作分组的多部分键,而不会产生潜在的大键:

    public class MultipartKey : IEquitable<MultipartKey> {
        private IList<string> parts;
        int hashCode;
        public MultipartKey(IEnumerable<string> parts) {
            this.parts = parts.OrderBy(s => s).ToList();
            hashCode = this.parts.Aggregate(0, (p, v) => 31*p + v.GetHashCode());
        }
        public override int GetHashCode() {
            return hashCode;
        }
        public override bool Equals(MultipartKey other) {
            return parts.SequenceEqual(other.Parts);
        }
    }
    

    并在这样的查询中使用它:

    objList = objList
        .GroupBy(x => new MultipartKey(x.StrList))
        .Select(g => g.OrderByDescending(x => x.Num).First())
        .ToList();
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-07-09
      • 2012-04-17
      • 1970-01-01
      • 2015-07-17
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多