75 Stimmen

Auswahl von Werten innerhalb eines angegebenen Indexbereichs aus einer Liste mit LINQ

Ich bin ein LINQ-Neuling, der versucht, es zu verwenden, um das Folgende zu erreichen:

Ich habe eine Liste von Ints:-

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

Jetzt möchte ich die Summe der ersten drei Elemente [Indexbereich 0-2] mit den letzten drei [Indexbereich 3-5] mit LINQ vergleichen. Ich habe die LINQ-Erweiterungsmethoden Select und Take sowie die SelectMany-Methode ausprobiert, aber ich kann nicht herausfinden, wie ich etwas sagen kann wie

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

Ich habe mir auch die Contains-Extension-Methode angesehen, aber das scheint mir nicht das zu bringen, was ich will. Irgendwelche Vorschläge? Danke!

109voto

Adam Sills Punkte 16598

Utilisez Überspringen dann nehmen.

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

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

41voto

Onuralp Punkte 880

Sie können GetRange() verwenden

list.GetRange(index, count);

18voto

Tao Punkte 12833

Bei größeren Listen könnte eine separate Erweiterungsmethode aus Leistungsgründen sinnvoller sein. Ich weiß, dass dies für den ursprünglichen Fall nicht notwendig ist, aber die Linq (to objects)-Implementierung beruht auf der Iteration der Liste, was bei großen Listen (sinnlos) teuer werden könnte. Eine einfache Erweiterungsmethode, um dies zu erreichen, könnte sein:

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

5voto

Jaroslav Kubacek Punkte 1349

Ab .NET 6 ist es möglich, die Bereichssyntax für die Take-Methode.

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

// Starting from index 0 (including) to index 3 (excluding) will select indexes (0, 1, 2)
Console.WriteLine(intList.Take(0..3).Sum()); // {1, 2, 3} -> 6

// By default is first index 0 and can be used following shortcut.
Console.WriteLine(intList.Take(..3).Sum());  // {1, 2, 3} -> 6      

// Starting from index 3 (including) to index 6 (excluding) will select indexes (3, 4, 5)
Console.WriteLine(intList.Take(3..6).Sum()); // {3, 2, 1} -> 6  

// By default is last index lent -1 and can be used following shortcut.
Console.WriteLine(intList.Take(3..).Sum());  // {3, 4, 5} -> 6

// Reverse index syntax can be used. Take last 3 items.
Console.WriteLine(intList.Take(^3..).Sum()); // {3, 2, 1} -> 6

// No exception will be raised in case of range is exceeded.
Console.WriteLine(intList.Take(^100..1000).Sum()); 

Also einfach ausgedrückt, intList.Take(..3).Sum() y intList.Take(3..).Sum() kann mit .NET 6 verwendet werden.

1voto

stomy Punkte 1469

Zum Filtern nach bestimmten Indizes (nicht von-bis):

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

Zum Beispiel:

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

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X