我如何使用跳过并接受linq

时间:2012-05-17 13:18:04

标签: c# linq

我有一个包含超过50k行的数据集。我决定取前五十个值的平均值,然后是第二个五十个值,依此类推(这样我就可以获得平均50个值组的数据集的一半)。

这是我的代码:

var Rate = (from dr in ds.Tables[0].AsEnumerable()
                                    select new
                                    {
                                        rate = dr.Field<double>(columnName)
                                    }.rate).ToList();
                            if (Rate.Count > 50)
                            {
                                var avg = Rate.CheckRateValue();
                            }

以下是我的扩展方法的代码:

public static IEnumerable<double> CheckRateValue(this IEnumerable<double> values)
{
    int i = 1;
    int j = 0;
    for (; i < values.Count(); )
    {
        yield return values.Skip(j * 2).Take(2).Average();
        i = i + 2;
        j++;
    }
}

问题: 它工作正常,但速度很慢。有没有人对如何加快它有任何建议?

6 个答案:

答案 0 :(得分:2)

使用DataTable.Compute可能会更快,因为您跳过迭代来创建List<dobule>

double average = (double)ds.Tables[0].Compute("avg(columnName)", "");

第二个参数是fitler表达式,因此如果表中的数据允许,您可以使用它来跳过它。

答案 1 :(得分:1)

var yourList=yourList.Take(50).Aggregate((acc, cur) => acc + cur) / list.Count

答案 2 :(得分:1)

如果你想以五十分的数量取物品并取平均值(比如前50,平均,接下来50,平均等),并获得平均值列表,你可以使用{{3} }。MoreLinq

您可以使用

  var result = list.Batch(50).Select(x=> x.Average());

答案 3 :(得分:0)

为什么这会比简单更快:

var average = dat.AsEnumerable().Average(dr => (double)dr["ColumnName"]);

事实上 - 这应该比一次服用50的额外复杂性更快......

答案 4 :(得分:0)

有 {   yield return values.Skip(j * 2).Take(2).Average(); }

在每次循环迭代中从头开始移动到当前页面:这将是n ^ 2。另请参阅Schlemiel the painter

您应该枚举values一次!

答案 5 :(得分:0)

通过使用row_number()我解决了它。

declare @Skip int = 20
declare @Take int = 10

select SomeColumn
from (
   select SomeColumn,
          row_number() over(order by SomeColumnToOrderBy) as rn
   from YourTable
 ) T
where rn > @Skip and 
  rn <= @Skip + @Take