【问题标题】:Accessing Rows In A LINQ Result Without A Foreach Loop?在没有 Foreach 循环的情况下访问 LINQ 结果中的行?
【发布时间】:2011-03-13 22:48:52
【问题描述】:

对于我编写的每个 LINQ 查询,我总是使用 foreach 循环来遍历结果。现在,我有一个程序,我想获取结果的前 50 行,对这些行进行一些计算,然后获取结果的下 50 行等。

使用 LINQ 和 C# 执行此操作的标准方法是什么?

【问题讨论】:

    标签: c# linq


    【解决方案1】:

    .Skip().Take() 在这种情况下将是最好的方法(就清晰而言)。例如:

    var results = db.Table.Select(); // Your query here
    
    int rowCount = results.Count(); // Count rows once and store
    
    for(int i = 0; i <= rowCount; i += 50)
    {
        var paged = results.Skip(i).Take(50);
    
        // do the calculations with the groups of 50 here
    }
    

    值得注意的是,即使这看起来更清楚(您从结果中抽取 50 个组),但每次调用 Skip() 和 Take() 时,都可能需要重新枚举集合...这实际上比简单地使用foreach 一次枚举结果效率低。

    【讨论】:

    • 如果对象是IEnumerable&lt;&gt;,这将遍历集合多次
    • 特定场景也可以显示将选择移动到循环结构中的效率更高。我也不确定在什么情况下 .Take 会因空枚举而失败(iow,rowCount 是不必要的)。
    • 如果这是针对IQueryable 对象,则很有可能将分页移至数据库。在这些情况下,我强烈建议采用这种方法。
    【解决方案2】:

    在不了解数据和/或计算的性质的情况下,执行此操作的“良好标准”方法可能是 foreach 循环!

    如果您能提供一些有关数据性质和您想要执行的计算的信息,将会有所帮助。取决于此,最佳答案可能是 foreachSkip/TakeGroupBy 或其他任何东西。

    【讨论】:

      【解决方案3】:

      有这样的效果

      var page = (From c In db.Customers Order By c.ContactName, c.City Descending
                       Select c).Skip(50).Take(50)
      

      【讨论】:

        【解决方案4】:

        您可以通过 ie 使用组:

        data.Select((item, index) => new {item, index}).GroupBy(g => g.index / 50)
        

        然后您将对每个组进行操作。

        类似这样:How to use Linq to group every N number of rows

        【讨论】:

          【解决方案5】:

          使用.Skip(...).Take(...) 将用于分页。但需要考虑的是,再次IEnumerable&lt;...&gt; 这将在每次处理时重新计算可枚举。这是消耗而不是可重置的东西,您可能会遇到问题。这个方法集可以解决这个问题。

          public static class EnumerableEx
          {
              public static IEnumerable<IEnumerable<T>> AsPages<T>(
                  this IEnumerable<T> set, int pageLength)
              {
                  using (var e = set.GetEnumerator())
                      while (true)
                          yield return GetPage(e, pageLength);
              }
              private static IEnumerable<T> GetPage<T>(
                 IEnumerator<T> set, int pageLength)
              {
                  for (var position = 0; 
                      position < pageLength && set.MoveNext(); 
                      position++)
                      yield return set.Current;
              }
          }
          

          ...这是一个为什么它很重要的用法示例。

          class Program
          {
              private static int _last = 0;
              private static IEnumerable<int> GetValues()
              {
                  while (true)
                      yield return _last++;
              }
          
              static void Main(string[] args)
              {
                  for (var i = 0; i < 3; i++)
                      foreach (var value in GetValues().Skip(5 * i).Take(5))
                          Console.Write(value + ",");
                  // 0,1,2,3,4,10,11,12,13,14,25,26,27,28,29,
                  Console.WriteLine();
                  _last = 0;
          
                  foreach (var page in GetValues().AsPages(5).Take(3))
                      foreach (var value in page)
                          Console.Write(value + ",");
                  // 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,
              }
          }
          

          【讨论】:

            猜你喜欢
            • 2011-01-15
            • 1970-01-01
            • 1970-01-01
            • 2017-10-31
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2018-05-12
            • 1970-01-01
            相关资源
            最近更新 更多