125 Stimmen

Wie kann ich jedes n-te Element aus einer List<T> erhalten?

Ich benutze .NET 3.5 und möchte in der Lage sein, jedes *n*te Element aus einer Liste zu erhalten. Es ist mir egal, ob dies mit einem Lambda-Ausdruck oder LINQ erreicht wird.

Bearbeiten

Sieht so aus, als ob diese Frage ziemlich viel Debatte ausgelöst hat (was ja gut ist, oder?). Das Hauptding, das ich gelernt habe, ist, dass man, wenn man denkt, dass man jeden Weg kennt, um etwas zu tun (selbst so etwas Einfaches wie das hier), nochmal nachdenken sollte!

5voto

belucha Punkte 71

Ich denke, dass wenn Sie eine Linq-Erweiterung bereitstellen, Sie in der Lage sein sollten, auf das ungenaueste Interface, also auf IEnumerable, zu arbeiten. Natürlich, wenn Sie besonders schnell sind, insbesondere für große N, könnten Sie eine Überladung für den indexierten Zugriff bereitstellen. Letzteres entfernt die Notwendigkeit, über große Mengen von nicht benötigten Daten zu iterieren, und wird viel schneller sein als die Where-Klausel. Das Bereitstellen beider Überladungen ermöglicht es dem Compiler, die am besten geeignete Variante auszuwählen.

public static class LinqExtensions
{
    public static IEnumerable GetNth(this IEnumerable list, int n)
    {
        if (n < 0)
            throw new ArgumentOutOfRangeException("n");
        if (n > 0)
        {
            int c = 0;
            foreach (var e in list)
            {
                if (c % n == 0)
                    yield return e;
                c++;
            }
        }
    }
    public static IEnumerable GetNth(this IList list, int n)
    {
        if (n < 0)
            throw new ArgumentOutOfRangeException("n");
        if (n > 0)
            for (int c = 0; c < list.Count; c += n)
                yield return list[c];
    }
}

3voto

Guffa Punkte 663241

Ich bin mir nicht sicher, ob es mit einem LINQ-Ausdruck möglich ist, aber ich weiß, dass du die Where-Erweiterungsmethode verwenden kannst. Zum Beispiel, um jedes fünfte Element zu erhalten:

List list = originalList.Where((t,i) => (i % 5) == 0).ToList();

Dies wird das erste Element und jedes fünftes Element von da an erhalten. Wenn du mit dem fünften Element beginnen möchtest anstatt mit dem ersten, vergleichst du mit 4 anstelle von 0.

1voto

user2340145 Punkte 11

Imho keine Antwort ist richtig. Alle Lösungen beginnen bei 0. Aber ich möchte das echte n-te Element haben

public static IEnumerable GetNth(this IList list, int n)
{
    for (int i = n - 1; i < list.Count; i += n)
        yield return list[i];
}

1voto

Spoc Punkte 618

@belucha Ich mag das, weil der Client-Code sehr lesbar ist und der Compiler die effizienteste Implementierung wählt. Ich würde darauf aufbauen, indem ich die Anforderungen auf IReadOnlyList reduziere und die Division für leistungsstarkes LINQ speichere:

    public static IEnumerable GetNth(this IEnumerable list, int n) {
        if (n <= 0) throw new ArgumentOutOfRangeException(nameof(n), n, null);
        int i = n;
        foreach (var e in list) {
            if (++i < n) { // Division speichern
                continue;
            }
            i = 0;
            yield return e;
        }
    }

    public static IEnumerable GetNth(this IReadOnlyList list, int n
        , int offset = 0) { // IReadOnlyList verwenden
        if (n <= 0) throw new ArgumentOutOfRangeException(nameof(n), n, null);
        for (var i = offset; i < list.Count; i += n) {
            yield return list[i];
        }
    }

0voto

Anwar Ul-Haq Punkte 1776
private static readonly string[] sequence = "1,2,3,4,5,6,7,8,9,10,11,12,13,14,15".Split(',');

static void Main(string[] args)
{
    var every4thElement = sequence
      .Where((p, index) => index % 4 == 0);

    foreach (string p in every4thElement)
    {
        Console.WriteLine("{0}", p);
    }

    Console.ReadKey();
}

Ausgabe

enter image description here

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