13

有没有一种好方法可以仅枚举 C# 中 Collection 的一个子集?也就是说,我有一个包含大量对象(例如 1000 个)的集合,但我只想枚举 250 - 340 个元素。有没有一种好方法可以为集合的子集获取枚举器,而无需使用另一个集合?

编辑:应该提到这是使用 .NET Framework 2.0。

4

6 回答 6

39

尝试以下

var col = GetTheCollection();
var subset = col.Skip(250).Take(90);

或更一般地说

public static IEnumerable<T> GetRange(this IEnumerable<T> source, int start, int end) {
  // Error checking removed
  return source.Skip(start).Take(end - start);
}

编辑2.0 解决方案

public static IEnumerable<T> GetRange<T>(IEnumerable<T> source, int start, int end ) {
  using ( var e = source.GetEnumerator() ){ 
    var i = 0;
    while ( i < start && e.MoveNext() ) { i++; }
    while ( i < end && e.MoveNext() ) { 
      yield return e.Current;
      i++;
    }
  }      
}

IEnumerable<Foo> col = GetTheCollection();
IEnumerable<Foo> range = GetRange(col, 250, 340);
于 2009-05-19T20:01:36.543 回答
3

我喜欢保持简单(如果您不一定需要枚举器):

for (int i = 249; i < Math.Min(340, list.Count); i++)
{
    // do something with list[i]
}
于 2009-05-19T20:08:10.180 回答
2

为 .Net 2.0 改编 Jared 的原始代码:

IEnumerable<T> GetRange(IEnumerable<T> source, int start, int end)
{
    int i = 0;
    foreach (T item in source)
    {
        i++;
        if (i>end) yield break;
        if (i>start) yield return item;
    }
}

并使用它:

 foreach (T item in GetRange(MyCollection, 250, 340))
 {
     // do something
 }
于 2009-05-19T20:11:21.703 回答
1

再次调整 Jarad 的代码,这种扩展方法将为您提供一个由item定义的子集,而不是 index。

    //! Get subset of collection between \a start and \a end, inclusive
    //! Usage
    //! \code
    //! using ExtensionMethods;
    //! ...
    //! var subset = MyList.GetRange(firstItem, secondItem);
    //! \endcode
class ExtensionMethods
{
    public static IEnumerable<T> GetRange<T>(this IEnumerable<T> source, T start, T end)
    {
#if DEBUG
        if (source.ToList().IndexOf(start) > source.ToList().IndexOf(end))
            throw new ArgumentException("Start must be earlier in the enumerable than end, or both must be the same");
#endif
        yield return start;

        if (start.Equals(end))
            yield break;                                                    //start == end, so we are finished here

        using (var e = source.GetEnumerator())
        { 
            while (e.MoveNext() && !e.Current.Equals(start));               //skip until start                
            while (!e.Current.Equals(end) && e.MoveNext())                  //return items between start and end
                yield return e.Current;
        }
    }
}
于 2015-07-15T11:41:48.900 回答
0

你也许可以用 Linq 做点什么。我这样做的方法是将对象放入一个数组中,然后我可以根据数组 id 选择要处理的项目。

于 2009-05-19T20:02:49.257 回答
0

如果您发现您需要对列表和集合进行大量切片和切块,则可能值得将学习曲线爬上C5 通用集合库

于 2009-05-19T20:05:17.317 回答