如何使用 LINQ 选择在一列中带条件

本文关键字:一列 条件 LINQ 何使用 选择 | 更新日期: 2023-09-27 18:31:48

像这样的数据表...

Date       Count
20160101   100
20160102   103
20160103   108
20160104   102
20160105   104
20160106   106
20160107   108

我要select if => someday.Count > someday[-3].Count

结果 = 下面的 3 行:

20160104,因为102>100
20160105,因为104>103
20160107,因为108>102

请告诉我如何使用 LINQ?
多谢

如何使用 LINQ 选择在一列中带条件

一种方法是这样做。

int index = 0;
var a = from i in someday
        let indexNow = index++
        where indexNow >= 3
        let j = someday[indexNow - 3]
        where i.Count > j.Count
        select i;

您创建临时变量 j 以在三步之前获取元素,然后将其与当前元素进行比较以检查它是否满足特定条件。如果是,则选择它

按如下方式使用索引Where -重载:

var result = myDates.Where((x, index) => index >= 3 && x > myDates.ElementAt(x - 3).Count);

这会从您的集合中选择所有那些元素,这些元素的计数比三天前的元素更多。

您可以使用

WhereFunc<TSource, int, bool> predicate作为输入的重载。此委托的第二个输入是当前元素的索引。因此,这意味着您的 lambda 表达式必须接受两个输入,第一个输入是元素的类型,另一个是Int32Where方法将自动计算当前元素的索引。

var result = myColl.Where((x, index) => index >= 3 && x.Count > myColl.ElementAt(index - 3).Count);

然后,您可以使用所需的方法,如Select()ToList()等。

PS:我假设对象的名称是myColl

此外:

我总是喜欢告诉开发人员有关http://referencesource.microsoft.com/的信息。您可以轻松找到所有方法的实现以及有关 C# 源代码的所有内容。如果您有兴趣,这里是Where方法重载的源代码。

    public static IEnumerable<TSource> Where<TSource>(this IEnumerable<TSource> source, Func<TSource, int, bool> predicate) {
        if (source == null) throw Error.ArgumentNull("source");
        if (predicate == null) throw Error.ArgumentNull("predicate");
        return WhereIterator<TSource>(source, predicate);
    }

如您所见,它将返回WhereIterator,它将自动计算当前项目的索引并将其发送到您的方法:

static IEnumerable<TSource> WhereIterator<TSource>(IEnumerable<TSource> source, Func<TSource, int, bool> predicate) {
    int index = -1;
    foreach (TSource element in source) {
        checked { index++; }
        if (predicate(element, index)) yield return element;
    }
}

虽然其他答案中描述的索引技术可以工作,但如果源序列不是基于列表的,它们将效率低下,在这种情况下ElementAt将导致 O(N^2) 时间复杂度运算。

对于仅 O(N) 时间复杂度(如果源序列本身不包含繁重的操作)的一种可能更好的方法是使用 Skip 和 Zip 的组合,如下所示

var result = myDates
    .Skip(3)
    .Zip(myDates, (current, compare) => current.Count > compare.Count ? current : null)
    .Where(item => item != null);