按一些标准从集合中选择最大项目

我是.net 3.5的新手。 我有一个项目集合:

IList models; 

哪里

 class Model { public string Name { get; private set; } } 

我想得到名称长度最长的元素。 我试过了

 string maxItem = models.Max(model => model.Name.Length); 

但它当然会返回最大长度(我需要一个Model对象)。 我知道有一种方法可以使用扩展方法,但我不知道如何。

这就是我开始工作的方式。 也许有更好的方法,我不确定:

  decimal de = d.Max(p => p.Name.Length); Model a = d.First(p => p.Name.Length == de); 

不幸的是,没有一种内置的方法可以做到这一点 – 但是编写一个扩展方法来实现它真的很容易。

事实上,这是我的第一篇博客文章之一……请注意,其中一条评论中有更好的实施方式。 如果我有时间,我会把它移到身体里。

编辑:好的,我有一个略有缩写的版本 – 它只使用给定的选择器返回最大元素。 也不需要进行投影 – 如果需要,可以在之后做一次。 请注意,您可以删除TValue上的约束并使用Comparer.Default ,或者具有允许将比较指定为另一个参数的重载。

 public static TSource MaxBy(this IEnumerable source, Func selector) where TValue : IComparable { TValue maxValue = default(TValue); TSource maxElement = default(TSource); bool gotAny = false; foreach (TSource sourceValue in source) { TValue value = selector(sourceValue); if (!gotAny || value.CompareTo(maxValue) > 0) { maxValue = value; maxElement = sourceValue; gotAny = true; } } if (!gotAny) { throw new InvalidOperationException("source is empty"); } return maxElement; } 

样本使用:(注意类型推断):

 string maxName = models.MaxBy(model => model.Name.Length).Name; 

这是另一种方法。 有一个版本的Max没有标准,并使用IComparable 。 因此,我们可以提供一种方法来包装可比对象中的任何内容,并使用委托提供比较。

 public class Comparable : IComparable> { private readonly T _value; private readonly Func _compare; public Comparable(T v, Func compare) { _value = v; _compare = compare; } public T Value { get { return _value; } } public int CompareTo(Comparable other) { return _compare(_value, other._value); } } 

然后我们可以说:

 Model maxModel = models.Select(m => new Comparable(m, (a, b) => a.Name.Length - b.Name.Length)).Max().Value; 

这涉及很多额外的分配,但它在学术上有点有趣(我认为)。

您可以使用Aggregate。 无需编写新的扩展方法即可完成。

 models.Aggregate( new KeyValuePair(), (a, b) => (a.Value < b.Name.Length) ? new KeyValuePair(b, b.Name.Length) : a, a => a.Key); 

使用扩展方法有什么好处吗?

也许一个简单迭代列表的方法或程序就足够了?

有效的东西

昏暗的结果为string = models(0).Name
对于每个m作为模型中的模型
  如果m.Name.length> result.length那么
     result = m.Name
  万一
下一个

另一种方式可能是:

 var item = (from m in models select m orderby m.Name.Length descending).FirstOrDefault(); 

第一个将是长度最长的一个。