2

我是.net 3.5 的新手。我有一系列物品:

IList<Model> models;

在哪里

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

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

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

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

4

6 回答 6

7

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

实际上,这是在我的第一篇博客文章中……请注意,其中一个评论中有更好的实现。如果我有时间,我会把它移到身体里。

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

public static TSource MaxBy<TSource, TValue>(this IEnumerable<TSource> source,
                                             Func<TSource, TValue> selector)
    where TValue : IComparable<TValue>
{
    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;
于 2008-12-21T16:44:11.683 回答
1

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

public class Comparable<T> : IComparable<Comparable<T>>
{
    private readonly T _value;
    private readonly Func<T, T, int> _compare;

    public Comparable(T v, Func<T, T, int> compare)
    {
        _value = v;
        _compare = compare;
    }

    public T Value { get { return _value; } }

    public int CompareTo(Comparable<T> other)
    {
        return _compare(_value, other._value);
    }
}

然后我们可以说:

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

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

于 2008-12-21T17:42:16.633 回答
0

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

    decimal de = d.Max(p => p.Name.Length);
    Model a = d.First(p => p.Name.Length == de);
于 2008-12-21T16:50:28.860 回答
0

使用扩展方法有什么收获吗?

也许具有简单迭代列表的方法或过程就足够了?

大意是什么

暗淡结果为 string = models(0).Name
对于每个 m 作为模型中的模型
  如果 m.Name.length > result.length 那么
    结果 = m.Name
  万一
下一个
于 2008-12-21T17:08:31.743 回答
0

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

models.Aggregate(
                new KeyValuePair<Model, int>(),
                (a, b) => (a.Value < b.Name.Length) ? new KeyValuePair<Model, int>(b, b.Name.Length) : a,
                a => a.Key);
于 2008-12-21T19:24:51.390 回答
-1

另一种方式可能是:

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

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

于 2008-12-21T17:10:34.843 回答