简体   繁体   English

我如何使用linq跳过和接收

[英]How I can do this using skip and take in linq

I have a dataset which contains more than 50k rows. 我有一个包含超过5万行的数据集。 I decided to take average of the first fifty values, then second fifty values and so on (so that I will get half of the Dataset with average of 50 value groups). 我决定取前50个值的平均值,再取后50个值的平均值,依此类推(这样我将获得50个值组平均值的数据集的一半)。

Here is my code: 这是我的代码:

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();
                            }

And here is the code for my extension method: 这是我的扩展方法的代码:

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++;
    }
}

Problem : It works fine but it's slow. 问题:可以正常运行,但是速度很慢。 Does anyone have any suggestions on how to speed it up? 有人对如何加快速度有任何建议吗?

Using the DataTable.Compute may be faster because you skip the iteration to create List<dobule> . 使用DataTable.Compute可能会更快,因为您跳过了创建List<dobule>的迭代。

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

The second parameter is a fitler expression so you could use it to do your skipping if the data in the table allows it. 第二个参数是fitler表达式,因此如果表中的数据允许,则可以使用它来跳过。

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

If you want to take items in count of fifty and average it (like take first 50 , average it, take next 50, average it, and so on), and get list of Averages, you can use MoreLinq . 如果您要获取数量为50的项目并将其平均(例如,前50个,平均,下一个50,平均等),并获取平均列表,则可以使用MoreLinq Batch 批量

You can use 您可以使用

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

Why would that be any faster than simply: 为什么会比简单地更快呢?

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

In fact - this should probably be faster than the extra complexity of taking 50 at a time... 实际上-这可能比一次服用50次额外的复杂性要快...

for { yield return values.Skip(j * 2).Take(2).Average(); 对于{收益率返回值。Skip(j * 2).Take(2).Average(); } }

Moving to the current page from the start in each loop iteration: that will be n^2. 在每个循环迭代中从头开始移至当前页面:那将是n ^ 2。 See also Schlemiel the painter . 另请参阅画家Schlemiel

You should enumerate values once! 您应该一次枚举values

By using row_number() i solved it. 通过使用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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM