Pregunta

¿Hay una buena manera para enumerar sólo un subconjunto de una colección en C #? Es decir, tengo una colección de un gran número de objetos (por ejemplo, 1000), pero me gustaría enumerar sólo los elementos 250 - 340. ¿Hay una buena manera de conseguir un enumerador para un subconjunto de la colección, sin utilizando otro Collection?

Edit:. Debería haber mencionado que este está utilizando .NET Framework 2.0

¿Fue útil?

Solución

Pruebe lo siguiente

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

O en términos más generales

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 Solución

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

Otros consejos

Me gusta que sea sencillo (si no necesariamente tienen el empadronador):

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

La adaptación de código original de 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;
    }
}

Y para utilizarlo:

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

La adaptación de código de Jarad, una vez más, este método de extensión le conseguirá un subconjunto que se define por elemento , no í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;
        }
    }
}

Usted puede ser capaz de hacer algo con LINQ. La forma en que lo haría esto es poner los objetos en una matriz, entonces puedo elegir qué elementos Quiero proceso basado en la matriz de identificación.

Si usted encuentra que usted tiene que hacer una buena cantidad de reordenamiento de las listas y colecciones, podría valer la pena subir la curva de aprendizaje en el C5 Colección Biblioteca genérica .

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top