Pergunta

Existe uma boa maneira para enumerar apenas um subconjunto de uma coleção em C #? Ou seja, eu tenho uma coleção de um grande número de objetos (por exemplo, 1000), mas eu gostaria de enumerar apenas os elementos 250 - 340. Existe uma boa maneira de obter um enumerador para um subconjunto da coleção, sem usando outro Collection?

Edit:. Deveria ter mencionado que isso é usando .NET Framework 2.0

Foi útil?

Solução

Tente o seguinte

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

ou, mais geralmente

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

Editar 2.0 Solução

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

Outras dicas

Eu gosto de mantê-lo simples (se você não precisa necessariamente o enumerador):

for (int i = 249; i < Math.Min(340, list.Count); i++)
{
    // do something with list[i]
}

código original de Adaptação Jared para .Net 2.0:

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

E para usá-lo:

 foreach (T item in GetRange(MyCollection, 250, 340))
 {
     // do something
 }

código de Adaptação Jarad, mais uma vez, este método extensão vai te dar um subconjunto que é definido pelo item , não índice.

    //! 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;
        }
    }
}

Você pode ser capaz de fazer algo com Linq. A maneira que eu iria fazer isso é colocar os objetos em uma matriz, então eu posso escolher quais itens Quero processo baseado na id matriz.

Se você achar que você precisa fazer uma quantidade razoável de fatiamento de listas e coleções, pode valer a pena subir a curva de aprendizagem em o acervo da biblioteca C5 Generic .

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top