184 Stimmen

foreach mit Index

Gibt es ein C#-Äquivalent zu Pythons enumerate() und Ruby's each_with_index ?

0 Stimmen

Wenn Sie LINQ verwenden, gibt es Überschreibungen der verschiedenen Funktionen, die eine Aufzählung ermöglichen. Ansonsten müssen Sie in der Regel eine Variable verwenden, die Sie selbst inkrementieren.

1 Stimmen

Können wir diese Frage auf C# 7.0 aktualisieren, wo es jetzt Tupel gibt? Ich frage mich, wie eine Lösung mit Tupeln aussehen würde.

0 Stimmen

Ist das nicht ein Merkmal von foreach dass Sie jedes Element absolut entkoppelt von seiner Position in der Liste verarbeiten können?

277voto

Dan Punkte 3151

Ich behalte diese Erweiterungsmethode für diesen Zweck bei:

public static void Each<T>(this IEnumerable<T> ie, Action<T, int> action)
{
    var i = 0;
    foreach (var e in ie) action(e, i++);
}

Und verwenden Sie es so:

var strings = new List<string>();
strings.Each((str, n) =>
{
    // hooray
});

Oder um zu ermöglichen break -ähnliches Verhalten:

public static bool Each<T>(this IEnumerable<T> ie, Func<T, int, bool> action)
{
    int i = 0;
    foreach (T e in ie) if (!action(e, i++)) return false;
    return true;
}

var strings = new List<string>() { "a", "b", "c" };

bool iteratedAll = strings.Each ((str, n)) =>
{
    if (str == "b") return false;
    return true;
});

30 Stimmen

Können Sie in dieser foreach-Schleife nicht unterbrechen.

30 Stimmen

Das liegt daran, dass es sich nicht um eine foreach-Schleife handelt.

6 Stimmen

@TriQ Das ist nur ein weiterer Grund, es zu bevorzugen, die meiste Zeit. :)

260voto

JaredPar Punkte 699699

Sie können Folgendes tun

foreach (var it in someCollection.Select((x, i) => new { Value = x, Index = i }) )
{
   if (it.Index > SomeNumber) //      
}

Dadurch wird für jeden Eintrag in der Sammlung ein Wert vom anonymen Typ erstellt. Er hat zwei Eigenschaften

  • Value : mit dem ursprünglichen Wert in der Sammlung
  • Index mit dem Index innerhalb der Sammlung

30 Stimmen

Clever, aber das ist so, als würde man sich mit der rechten Hand am linken Ohr kratzen. Ich schätze, ich werde den Index einfach selbst behalten, damit ich zukünftige Betreuer nicht verwirre.

2 Stimmen

A für den Aufwand, aber F für die allgemeine Lesbarkeit und Wartung. Entschuldigung.

50 Stimmen

@Neil, ich bin erstaunt, dass die Leute glauben, dies sei ein Wartungsproblem. Diese Überladung von Select (und anderen LINQ-Methoden) wurde genau zu dem Zweck bereitgestellt, um Operationen wie diese durchzuführen.

75voto

David Morton Punkte 15950

Die C# foreach hat keinen eingebauten Index. Sie müssen außerhalb der foreach-Schleife eine Ganzzahl hinzufügen und diese jedes Mal inkrementieren.

int i = -1;
foreach (Widget w in widgets)
{
   i++;
   // do something
}

Alternativ können Sie auch eine standardmäßige for-Schleife wie folgt verwenden:

for (int i = 0; i < widgets.Length; i++)
{
   w = widgets[i];
   // do something
}

22 Stimmen

Ich denke, Sie sollten i auf -1 initialisieren und zu Beginn des Schleifenkörpers inkrementieren, um sicherzustellen, dass eine "continue"-Anweisung keine Probleme verursacht.

9 Stimmen

@DrJokepu warum behalten Sie nicht einfach i = 0 und inkrementieren es vor der schließenden Klammer der foreach-Anweisung? Die Initialisierung mit etwas != 0 erregt die Aufmerksamkeit, wenn man später den Code durchsucht...

0 Stimmen

In Javascript gearbeitet

17voto

Jon Skeet Punkte 1325502

Abgesehen von den bereits gegebenen LINQ-Antworten, habe ich eine "SmartEnumerable" Klasse, die es Ihnen ermöglicht, den Index und die "first/last"-ness zu erhalten. Es ist ein bisschen hässlich in Bezug auf die Syntax, aber Sie können es nützlich finden.

Wir können wahrscheinlich die Typinferenz mit einer statischen Methode in einem nicht-generischen Typ verbessern, und implizite Typisierung wird auch helfen.

2 Stimmen

Großartig! Diese kleinen Hilfseigenschaften (first/last/index) sollten in das Standard-.net-Framework aufgenommen werden!

0 Stimmen

Es ist großartig, ich mag nur seinen langen und nicht beschreibenden Namen nicht

17voto

Daniel K Punkte 877

Ich mag die Möglichkeit, foreach zu verwenden, also habe ich eine Erweiterungsmethode und eine Struktur erstellt:

public struct EnumeratedInstance<T>
{
    public long cnt;
    public T item;
}

public static IEnumerable<EnumeratedInstance<T>> Enumerate<T>(this IEnumerable<T> collection)
{
    long counter = 0;
    foreach (var item in collection)
    {
        yield return new EnumeratedInstance<T>
        {
            cnt = counter,
            item = item
        };
        counter++;
    }
}

und ein Anwendungsbeispiel:

foreach (var ii in new string[] { "a", "b", "c" }.Enumerate())
{
    Console.WriteLine(ii.item + ii.cnt);
}

Eine gute Sache ist, dass Sie die Python-Syntax auch dann verwenden können, wenn Sie mit ihr vertraut sind:

foreach (var ii in Enumerate(new string[] { "a", "b", "c" }))

0 Stimmen

Welcher Teil dieses letzten Teils sieht für Sie wie Python-Syntax aus?

0 Stimmen

Entschuldigung für den Necropost. Ich modifiziert Ihre Funktion, so dass es hübsch und mehr pythonic in Gebrauch aussieht: pastebin.com/aExvenyY

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