【问题标题】:How do I limit the number of elements iterated over in a foreach loop?如何限制在 foreach 循环中迭代的元素数量?
【发布时间】:2011-01-02 03:07:44
【问题描述】:

我有以下代码

foreach (var rssItem in rss.Channel.Items)
{
    // ...
}

但只想要 6 个项目而不是所有项目,我该如何在 C# 中做到这一点?

【问题讨论】:

  • 哪 6 个?有6个吗?前6个?随机6?满足一定条件的 6 个?
  • 如果var在问题的示例代码中,它是C# 3.0+

标签: c# loops foreach


【解决方案1】:

只需遍历集合中的前 6 个:

foreach(var rssItem in rss.Channel.Items.Take(6))

【讨论】:

  • 当您说“太慢”时,您是指迭代集合所需的时间还是太慢而无法发布答案?
  • 我在寻找功能原语。正是如此。谢谢!
【解决方案2】:

不要太明显,但是...

int max = Math.Min(6, rss.Channel.Items.Count);
for (int i = 0; i < max; i++)
{
   var rssItem = rss.Channel.Items[i];
   //...
}

我知道这是老派,并没有充满各种扩展方法的优点,但有时老派仍然有效......尤其是如果您仍在使用 .NET 2.0。

【讨论】:

  • 如果序列没有索引器怎么办?例如,假设它是一个由随机生成的数字组成的无限序列。
  • 它仍然适用于列表或数组,rss.Channel.Items 可能就是这样。显然,如果 Linq 是一个选项,“Take”会更简单。
  • 我建议对 5.0 版进行语言改进。 for(;;)、++ 运算符等需要设置“oldschool”上下文,例如当前“不安全”
  • 正如我所说...有时 Linq 和 Extension 方法不是您正在使用的框架版本的选项 b/c。
  • +1,有时你不能总是使用最新最好的! :)
【解决方案3】:

使用Enumerable.Take:

foreach(var rssItem in rss.Channel.Items.Take(6)) {
    // go time!
}

注意

rss.Channel.Items.Take(6)

除了实例化IEnumerable 的实现之外什么都不做,可以迭代以产生枚举中的前六个项目。这是 LINQ to Objects 的延迟执行功能。

进一步注意,这是假设 .NET 3.5。如果您使用的是 .NET 的早期版本,则可以使用以下内容:

static IEnumerable<T> Take<T>(IEnumerable<T> source, int take) {
    if (source == null) {
        throw new ArgumentNullException("source");
    }
    if (take < 0) {
        throw new ArgumentOutOfRangeException("take");
    }
    if (take == 0) {
        yield break;
    }
    int count = 0;
    foreach (T item in source) {
        count++;
        yield return item;
        if (count >= take) {
            yield break;
        }
    }
}

然后:

foreach(var rssItem in Take(rss.Channel.Items, 6)) {
    // go time!
}

这假定 .NET 2.0。如果您不使用 .NET 2.0,则应该认真考虑升级。

【讨论】:

【解决方案4】:

如果您不想使用 linq,也可以跳出循环。

        int count = 0;
        foreach (var rssItem in rss.Channel.Items)
        {
            if (++count == 6) break;
            ...
        }

【讨论】:

    【解决方案5】:

    如果您对某个条件感兴趣(即按创建日期排序

    foreach(var rssItem in rss.Channel.Items.OrderByDescending(x=>x.CreateDate).Take(6)) 
    {
    //do something
    }
    

    也许如果您想获得由某个用户创建的那些,具有相同的排序

    foreach(var rssItem in rss.Channel.Items
                              .Where(x=>x.UserID == 1)
                              .OrderByDescending(x=>x.CreateDate)
                              .Take(6)) 
    {
    //do something
    }
    

    【讨论】:

      【解决方案6】:
      rss.Channel.Items.Take(6)
      

      【讨论】:

        猜你喜欢
        • 2011-10-14
        • 1970-01-01
        • 1970-01-01
        • 2012-08-02
        • 2021-07-21
        • 2016-07-06
        • 1970-01-01
        • 2022-11-22
        • 1970-01-01
        相关资源
        最近更新 更多