c# - 不使用 IComparable<T> 查找最大/最小元素

标签 c# .net list max min

假设我有以下内容:

public Class BooClass
{
   public int field1;
   public double field2;
   public DateTime field3;
}

public List<BooClass> booList;

例如,如何使用 booList.Find() 获取 field3 中时间最早的元素

编辑 抱歉,为了简化示例,我打算公开所有字段。我知道可以在 linq 中完成,我想知道 Find 方法是否有简单的单行条件。

最佳答案

F# 很方便 minBymaxBy运算符,我喜欢将其实现为 C# 扩展方法,因为 Linq 库省略了它们。这有点工作,但只是一点点,它可以让你避免复杂的表达式,比如

var earliest = booList.First(b => b.Field3 == booList.Min(e => e.Field3));

相反,您可以输入:

var earliest = booList.MinBy(b => b.Field3);

一个简单的实现:

static T MinBy<T, C>(this IEnumerable<T> sequence, Func<T, C> keySelector)
{
    bool first = true;
    T result = default(T);
    C minKey = default(C);
    IComparer<C> comparer = Comparer<C>.Default; //or you can pass this in as a parameter

    foreach (var item in sequence)
    {
        if (first)
        {
            result = item;
            minKey = keySelector.Invoke(item);
            first = false;
            continue;
        }

        C key = keySelector.Invoke(item);
        if (comparer.Compare(key, minKey) < 0)
        {
            result = item;
            minKey = key;
        }
    }

    return result;
}

这也比顶部的复杂表达式更有效,因为 MinBy 只迭代序列一次,而表达式迭代多次且小于或等于两次。当然,排序然后取第一项需要排序,这是O(n log n),而这只是O(n)。

正如 Saeed Amiri 所指出的,如果您依赖 Linq to SQL 或任何其他 IQueryable<>,此方法将不起作用提供商。 (更准确地说,它工作效率低下,因为它从数据库中提取对象并在本地处理它们。)对于不这样做的解决方案,请参阅 Saeed's answer .

您也可以基于该方法创建一个扩展方法,但由于我现在正在打电话,所以我会将实现留作众所周知的“读者练习”。

关于c# - 不使用 IComparable<T> 查找最大/最小元素,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8758581/

相关文章:

c# - 创建数组属性是否有意义?

.net - 使用 XSLT 生成 PDF 文档

.net - 什么是法师,它有什么用处?

c# - 检测特定参数异常?

c# - 具有丰富类型的 C# 中的 Const 正确性

c# - 将 .NET 应用程序的异常记录到 zabbix

python - 从某个索引开始迭代列表

list - Lisp 中的 (list ...) 与 '(...)

java - 创建列表数组

c# - 如何在外部浏览器中打开 webBrowser 控件中的链接?