代码之家  ›  专栏  ›  技术社区  ›  Paul Sonier

在C中枚举集合的子集

  •  11
  • Paul Sonier  · 技术社区  · 15 年前

    有没有一种好的方法可以只枚举C中集合的一个子集?也就是说,我有大量对象的集合(比如1000个),但我只想枚举250-340元素。是否有一种好的方法可以在不使用其他集合的情况下为集合的子集获取枚举器?

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

    6 回复  |  直到 9 年前
        1
  •  36
  •   JaredPar    15 年前

    尝试以下操作

    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解

    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);
    
        2
  •  3
  •   Fredrik Mörk    15 年前

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

    for (int i = 249; i < Math.Min(340, list.Count); i++)
    {
        // do something with list[i]
    }
    
        3
  •  2
  •   Joel Coehoorn    15 年前

    为.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
     }
    
        4
  •  1
  •   Jim    9 年前

    再次调整jarad的代码,这个扩展方法将为您提供一个由 项目 不是索引。

        //! 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;
            }
        }
    }
    
        5
  •  0
  •   Jeff    15 年前

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

        6
  •  0
  •   Yes - that Jake.    15 年前

    如果您发现需要对列表和集合进行大量的切片和切分,那么将学习曲线扩展到 the C5 Generic Collection Library .