Enumerar a través de un subconjunto de una colección en C #?
-
23-08-2019 - |
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
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 .