C# Linq按最快日期获取第一行订单,其中B列不是;“过期”;或;“已取消”;

C# Linq按最快日期获取第一行订单,其中B列不是;“过期”;或;“已取消”;,c#,linq,C#,Linq,我有一份清单 public Class Fruit { public int id; public string status; public DateTime time; public .... other columns } 我有一张这样的桌子 458 2015-03-19 00:00:00.000 Completed 469 2015-03-23 00:00:00.000 Inprogress 467 2015-02

我有一份清单

public Class Fruit
{
   public int id;
   public string status;
   public DateTime time;
   public .... other columns
}
我有一张这样的桌子

458       2015-03-19 00:00:00.000   Completed
469       2015-03-23 00:00:00.000   Inprogress  
467       2015-02-21 00:00:00.000   Overdue 
470       2015-05-25 00:00:00.000   Completed   
我只想在最快的日期前订购一行,但状态为“正在进行”或“过期”,在上面我想要这个

467       2015-02-21 00:00:00.000   Overdue 
我不知道怎么做但我试过了

var fruits = fruits.order(p => p.time);
var // not sure whats next
OrderBy()
First()
一起使用:

OrderBy()
First()
一起使用:


您可以使用
FirstOrDefault()
选择满足特定条件的第一个项目,或者如果没有此类项目,则使用
null

var firstNotExpired = fruits.OrderBy(f => f.time)
                            .FirstOrDefault(f => !(f.status == "Expired" || 
                                                   f.status == "Cancelled"));
这很好而且简洁,但是效率很低,因为它需要对整个列表进行排序。这更有效:

var firstNotExpired = fruits.Where(f => !(f.status == "Expired" || 
                                          f.status == "Cancelled"))
                            .OrderBy(f => f.time)
                            .FirstOrDefault();

您可以使用
FirstOrDefault()
选择满足特定条件的第一个项目,或者如果没有此类项目,则使用
null

var firstNotExpired = fruits.OrderBy(f => f.time)
                            .FirstOrDefault(f => !(f.status == "Expired" || 
                                                   f.status == "Cancelled"));
这很好而且简洁,但是效率很低,因为它需要对整个列表进行排序。这更有效:

var firstNotExpired = fruits.Where(f => !(f.status == "Expired" || 
                                          f.status == "Cancelled"))
                            .OrderBy(f => f.time)
                            .FirstOrDefault();

出于好奇,我想说: 如果您正在对对象执行LINQ操作(因此您的
fruits
不是db),那么执行
OrderBy
是一个
O(nlogn)
操作,在这种情况下是无用的。。。使用(稍作更改,因为
MinBy()
不支持空枚举):

公共静态类EnumerableTools
{
公共静态TSource MinByOrDefault(此IEnumerable源,Func选择器)
{
IComparer comparer=comparer.Default;
使用(var sourceIterator=source.GetEnumerator())
{
如果(!sourceIterator.MoveNext())
{
//空源
返回默认值(TSource);
}
var min=sourceIterator.Current;
var minKey=选择器(最小值);
while(sourceIterator.MoveNext())
{
var current=sourceIterator.current;
var currentKey=选择器(当前);
if(比较器比较(currentKey,minKey)<0)
{
最小值=电流;
minKey=currentKey;
}
}
返回最小值;
}
}
}

这保证在时间上是
O(n)
,在空间上是
O(1)
(不需要排序,也不分配额外的空间)

只是出于好奇,我要提到: 如果您正在对对象执行LINQ操作(因此您的
fruits
不是db),那么执行
OrderBy
是一个
O(nlogn)
操作,在这种情况下是无用的。。。使用(稍作更改,因为
MinBy()
不支持空枚举):

公共静态类EnumerableTools
{
公共静态TSource MinByOrDefault(此IEnumerable源,Func选择器)
{
IComparer comparer=comparer.Default;
使用(var sourceIterator=source.GetEnumerator())
{
如果(!sourceIterator.MoveNext())
{
//空源
返回默认值(TSource);
}
var min=sourceIterator.Current;
var minKey=选择器(最小值);
while(sourceIterator.MoveNext())
{
var current=sourceIterator.current;
var currentKey=选择器(当前);
if(比较器比较(currentKey,minKey)<0)
{
最小值=电流;
minKey=currentKey;
}
}
返回最小值;
}
}
}

这保证在时间上是
O(n)
,在空间上是
O(1)
(不需要排序,也不分配额外的空间)

所以你想要按时间顺序进行或过期的水果?旁注:如果第467项的日期为
2015
,或
2018
,则创建一个枚举可能会更有意义?是什么?你可能想考虑使用<代码> EnUM <代码> >你的代码>状态< /代码>属性……所以你想要的是正在进行的或过期的按时间排序的水果?旁注:如果第467项的日期为
2015
,或
2018
,则创建一个枚举可能会更有意义?您可能想考虑使用<代码> EnUM <代码> >代码>状态> <代码>属性…@ XANATOS,这是一个有效的点,我也思考了<代码> FrestRealSuth。然而,OP根本没有提到Linq到实体或数据库(仅“表”)。此外,有时您确实希望在找不到任何东西的情况下抛出异常。@xanatos,这是一个有效的观点,我也考虑了
FirstOrDefault
。然而,OP根本没有提到Linq到实体或数据库(仅“表”)。此外,有时您确实希望在找不到任何异常的情况下抛出异常。
public static class EnumerableTools
{
    public static TSource MinByOrDefault<TSource, TKey>(this IEnumerable<TSource> source, Func<TSource, TKey> selector)
    {
        IComparer<TKey> comparer = Comparer<TKey>.Default;

        using (var sourceIterator = source.GetEnumerator())
        {
            if (!sourceIterator.MoveNext())
            {
                // Empty source
                return default(TSource);
            }

            var min = sourceIterator.Current;
            var minKey = selector(min);

            while (sourceIterator.MoveNext())
            {
                var current = sourceIterator.Current;
                var currentKey = selector(current);

                if (comparer.Compare(currentKey, minKey) < 0)
                {
                    min = current;
                    minKey = currentKey;
                }
            }

            return min;
        }
    }
}