web-dev-qa-db-fra.com

Comment sélectionner des valeurs dans une plage d'index fournie dans une liste à l'aide de LINQ

Je suis un débutant LINQ essayant de l'utiliser pour atteindre les objectifs suivants:

J'ai une liste d'ints: -

List<int> intList = new List<int>(new int[]{1,2,3,3,2,1});

Maintenant, je veux comparer la somme des trois premiers éléments [plage d'index 0-2] avec les trois derniers [plage d'index 3-5] à l'aide de LINQ. J'ai essayé les méthodes d'extension LINQ Select and Take ainsi que la méthode SelectMany, mais je n'arrive pas à comprendre comment dire quelque chose comme 

(from p in intList  
where p in  Take contiguous elements of intList from index x to x+n  
select p).sum()

J'ai aussi regardé la méthode d'extension Contains, mais cela ne m'a pas permis d'obtenir ce que je veux. Aucune suggestion? Merci.

57
Punit Vora

Utilisez Skip then Take.

yourEnumerable.Skip(4).Take(3).Select( x=>x )

(from p in intList.Skip(x).Take(n) select p).sum()
83
Adam Sills

Vous pouvez utiliser GetRange ()

list.GetRange(index, count);
32
Onuralp

Pour les listes plus volumineuses, une méthode d'extension distincte pourrait être plus appropriée pour les performances. Je sais que ce n'est pas nécessaire pour le cas initial, mais l'implémentation de Linq (to objects) repose sur l'itération de la liste. Cela peut donc être coûteux (inutile) pour les grandes listes. Une méthode d'extension simple pour y parvenir pourrait être:

public static IEnumerable<TSource> IndexRange<TSource>(
    this IList<TSource> source,
    int fromIndex, 
    int toIndex)
{
    int currIndex = fromIndex;
    while (currIndex <= toIndex)
    {
        yield return source[currIndex];
        currIndex++;
    }
}
17
Tao

Pour filtrer par index spécifiques (pas de-à):

public static class ListExtensions
{
   public static IEnumerable<TSource> ByIndexes<TSource>(this IList<TSource> source, params int[] indexes)
   {        
        if (indexes == null || indexes.Length == 0)
        {
            foreach (var item in source)
            {
                yield return item;
            }
        }
        else
        {
            foreach (var i in indexes)
            {
                if (i >= 0 && i < source.Count)
                    yield return source[i];
            }
        }
   }
}

Par exemple:

string[] list = {"a1", "b2", "c3", "d4", "e5", "f6", "g7", "h8", "i9"};
var filtered = list.ByIndexes(5, 8, 100, 3, 2); // = {"f6", "i9", "d4", "c3"};
0
stomy