【问题标题】:Find minimal and maximal date in array using LINQ?使用LINQ在数组中查找最小和最大日期?
【发布时间】:2011-01-09 02:39:04
【问题描述】:

我有一个属性为Date 的类数组,即:

class Record
{
    public DateTime Date { get; private set; }
}

void Summarize(Record[] arr)
{
    foreach (var r in arr)
    {
        // do stuff 
    }
}

我必须在这个数组中找到earliest(最小值)和latest(最大值)日期。

如何使用 LINQ 做到这一点?

【问题讨论】:

  • “高效”和“最佳”需要上下文。您更喜欢在空间(内存使用、代码大小)或时间(运行时间、编译时间)方面高效的算法?

标签: c# .net linq arrays search


【解决方案1】:

如果要查找最早或最晚的日期:

DateTime earliest = arr.Min(record => record.Date);
DateTime latest   = arr.Max(record => record.Date);

Enumerable.Min, Enumerable.Max


如果要查找日期最早或最晚的记录:

Record earliest = arr.MinBy(record => record.Date);
Record latest   = arr.MaxBy(record => record.Date);

见:How to use LINQ to select object with minimum or maximum property value

【讨论】:

  • 绝对是最易读的方式。就纯粹的效率而言,这不是最有效的。不过,我怀疑这段代码会成为瓶颈。
  • @Keith Rousseau:为什么让你认为这不是“最有效的”?
  • @drj:它迭代数组两次。然而,同样的复杂性,常数因子翻了一番。
  • @Keith Rousseau 等人:小心微优化。仅当您知道这是一个问题时才进行优化。具有可读性/可维护性,直到/除非您知道这是一个问题。在大多数情况下,这个解决方案很好。
  • @Brian:我并不是说你应该优化这段代码。我只是指出,从纯粹的效率角度来看,它并不是最有效的。
【解决方案2】:

没有 LINQ 的老式解决方案:

DateTime minDate = DateTime.MaxValue;
DateTime maxDate = DateTime.MinValue;
foreach (var r in arr) 
{
    if (minDate > r.Date)
    {
        minDate = r.Date;
    }
    if (maxDate < r.Date)
    {
        maxDate = r.Date;
    }
}

【讨论】:

  • 好的,对于反对者:原始问题是:with C#,并被编辑为with LINQ
  • 事实上,你搞错了:(minDate > r.Date) 和 (maxDate
【解决方案3】:

二合一 LINQ 查询(和一个遍历):

arr.Aggregate(
    new { MinDate = DateTime.MaxValue,
          MaxDate = DateTime.MinValue },
    (accDates, record) => 
        new { MinDate = record.Date < accDates.MinDate 
                        ?  record.Date 
                        : accDates.MinDate,
              MaxDate = accDates.MaxDate < record.Date 
                        ?  record.Date 
                        : accDates.MaxDate });

【讨论】:

【解决方案4】:

使用 lambda 表达式:

void Summarise(Record[] arr)
{
    if (!(arr == null || arr.Length == 0))
    {
        List<Record> recordList = new List<Record>(arr);
        recordList.Sort((x,y) => { return x.Date.CompareTo(y.Date); });

        // I may have this the wrong way round, but you get the idea.
        DateTime earliest = recordList[0];
        DateTime latest = recordList[recordList.Count];
    }
}

基本上:

  • 按日期排序到新列表中
  • 选择该列表的第一个和最后一个元素

更新:考虑一下,如果您完全关心性能,我不确定这是否是这样做的方法,因为对整个列表进行排序将导致更多的比较,而不仅仅是扫描最高/最低值。

【讨论】:

    【解决方案5】:

    我只需创建两个属性 Min,Max,将您添加到数组中的第一项的值分配给它们,然后每次添加新项时只需检查其 DateTime 是否小于或大于 Min Max 的值.

    它既好又快,并且比每次需要获取 Min Max 时遍历数组要快得多。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2017-09-04
      • 2012-09-05
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-03-12
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多