排序列表并根据排序依据选择对象

时间:2019-03-27 12:42:08

标签: c# list linq

我有一个List<MyClass>,其中包含StatusDate字段。我想返回一个MyClass,其中Status = X

问题是列表中可能有多个,在这种情况下,我想对Date进行排序并返回最新的。

这可以在LINQ中用单个表达式完成吗?

3 个答案:

答案 0 :(得分:3)

您可以使用lambda表达式:

var yourResult = dbo.YourList.OrderByDescending(t=>t.Date).FirstOrDefault(t=>t.Status == 'X');

答案 1 :(得分:1)

如果list已位于内存中,请尝试以下操作:

var answer = list.Where(x => x.Status == X).OrderBy(x => x.Date).LastOrDefault();

对于Entity Framework,请尝试另一种方法:

var answer = context.Table.Where(x => x.Status == X).OrderByDescending(x => x.Date).FirstOrDefault();

答案 2 :(得分:0)

因此,您需要一个MyClass对象和一个对象X的序列,并且想要找到最新的MyClass对象,该对象的Status值等于{{ 1}}

X

尽管这行得通,但是排序不是很有效:找到第一个元素后,它将对第二,第三等进行排序,而您知道它不会使用其他元素,那么为什么对它们排序呢?如果您使用var result = myList.Where(myItem => myItem.Status == X) .OrderByDescending(myItem => myItem.Date) .FirstOrDefault(); ,则只需枚举一次

Aggregate

这会将第一个元素放在newestItem中,并扫描列表的其余部分。如果任何nextItem包含新数据,则将该下一个项目放在newestItem中,否则不要更改newestItem。最后返回newestItem,这是您想要的最新日期。

仅当您确定在位置之后至少还有一个剩余项目时,此方法才有效。如果还必须使用空列表,请考虑创建扩展功能:

var result = myList.Where(...)
    .Aggregate( (newestItem, nextItem) => (newestItem.Date < nextItem.Date) ? 
           newestItem : nextItem);

用法:

static TResult GetNewestOrDefault<TSource, TResult>(this IEnumerable<TSource> source,
   Func<Tsource, DateTime> dateSelector)
{
    var enumerator = source.GetEnumerator();

    if (enumerator.MoveNext())
    {   // at least one element; initialize newest:
        TSource newestElement = enumerator.Current;
        DateTime newestDate = dateSelector(newest);

        // scan the rest of the sequence and check if newer:
        while (enumerator.MoveNext())
        {
            Tsource nextElement = enumerator.Current;
            Datetime nextDate = dateSelector(nextElement);

            // if next element has a newer date, remember it as newest:

            if (newestDate < nextDate
            {
                newestElement = nextElement;
                newestDate = nextDate,
            }
        }
        // scanned all elements exactly once
        return newestElement;
    }
    else
       // empty sequence, return default
       return default(TResult);
}

这将扫描您的序列一次。