Question

Y at-il un bon moyen d'énumérer un sous-ensemble d'une collection en C #? C'est, j'ai une collection d'un grand nombre d'objets (par exemple, 1000), mais je voudrais énumérer seulement les éléments 250 - 340. Est-il un bon moyen d'obtenir un recenseur pour un sous-ensemble de la collection, sans en utilisant une autre collection?

Edit:. Aurait dû mentionner que ce utilise .NET Framework 2.0

Était-ce utile?

La solution

Effectuez les opérations suivantes

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

Ou plus généralement

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

EDIT 2.0 Solution

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

Autres conseils

Je tiens à garder les choses simples (si vous ne devez pas nécessairement le recenseur):

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

L'adaptation du code original de Jared pour .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;
    }
}

Et pour l'utiliser:

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

L'adaptation du code de Jarad encore une fois, cette méthode extention vous obtiendrez un sous-ensemble qui est défini par élément , ne pas indexer.

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

Vous pourriez être en mesure de faire quelque chose avec LINQ. La façon dont je le faire est de mettre les objets dans un tableau, je peux choisir les éléments que je veux traiter en fonction de l'identifiant du tableau.

Si vous trouvez que vous devez faire une bonne quantité de découpage en dés et de trancher les listes et les collections, il est peut-être la peine de monter la courbe d'apprentissage dans la Bibliothèque Collection générique C5 .

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top