Existe-t-il un équivalent en C # de enumerate()
de Python et de each_with_index
de Ruby?
Je garde cette méthode d'extension pour cela:
public static void Each<T>(this IEnumerable<T> ie, Action<T, int> action)
{
var i = 0;
foreach (var e in ie) action(e, i++);
}
Et utilisez-le comme ceci:
var strings = new List<string>();
strings.Each((str, n) =>
{
// hooray
});
Ou pour permettre un comportement de type break
-:
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;
});
Vous pouvez faire ce qui suit
foreach (var it in someCollection.Select((x, i) => new { Value = x, Index = i }) )
{
if (it.Index > SomeNumber) //
}
Cela créera une valeur de type anonyme pour chaque entrée de la collecte. Il aura deux propriétés
Le C # foreach n'a pas d'index intégré. Vous devrez ajouter un entier en dehors de la boucle foreach et l'incrémenter à chaque fois.
int i = -1;
foreach (Widget w in widgets)
{
i++;
// do something
}
Vous pouvez également utiliser une boucle standard comme suit:
for (int i = 0; i < widgets.Length; i++)
{
w = widgets[i];
// do something
}
J'aime pouvoir utiliser foreach, alors j'ai créé une méthode d'extension et une structure:
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++;
}
}
et un exemple d'utilisation:
foreach (var ii in new string[] { "a", "b", "c" }.Enumerate())
{
Console.WriteLine(ii.item + ii.cnt);
}
Une bonne chose est que si vous êtes habitué à la syntaxe Python, vous pouvez toujours l'utiliser:
foreach (var ii in Enumerate(new string[] { "a", "b", "c" }))
En plus des réponses LINQ déjà données, j'ai une classe "SmartEnumerable" qui vous permet d'obtenir l'index et le "premier/dernier". C'est un peu moche en termes de syntaxe, mais vous le trouverez peut-être utile.
Nous pouvons probablement améliorer l'inférence de type en utilisant une méthode statique dans un type non générique, et le typage implicite aidera également.
Ma solution implique une classe Pair simple que j'ai créée pour un usage général et qui, sur le plan opérationnel, est essentiellement identique à la classe d'infrastructure KeyValuePair. Ensuite, j'ai créé un couple de fonctions d'extension pour IEnumerable appelé Ordinate (à partir du terme de théorie des ensembles " ordinal ").
Ces fonctions renverront pour chaque élément un objet Pair contenant l'index et l'élément lui-même.
public static IEnumerable<Pair<Int32, X>> Ordinate<X>(this IEnumerable<X> lhs)
{
return lhs.Ordinate(0);
}
public static IEnumerable<Pair<Int32, X>> Ordinate<X>(this IEnumerable<X> lhs, Int32 initial)
{
Int32 index = initial - 1;
return lhs.Select(x => new Pair<Int32, X>(++index, x));
}
Non, il n'y en a pas.
Comme d'autres personnes l'ont montré, il existe des moyens de simuler le comportement de Ruby. Mais il est possible d'avoir un type qui implémente IEnumerable qui n'expose pas un index.
Ceci est votre collection
var values = new[] {6, 2, 8, 45, 9, 3, 0};
Faire une plage d'index pour cette collection
var indexes = Enumerable.Range(0, values.Length).ToList();
Utilisez la plage pour itérer avec index
indexes.ForEach(i => values[i] += i);
indexes.ForEach(i => Console.Write("[{0}] = {1}", i, values[i]));
Je viens de trouver une solution intéressante:
public class DepthAware<T> : IEnumerable<T>
{
private readonly IEnumerable<T> source;
public DepthAware(IEnumerable<T> source)
{
this.source = source;
this.Depth = 0;
}
public int Depth { get; private set; }
private IEnumerable<T> GetItems()
{
foreach (var item in source)
{
yield return item;
++this.Depth;
}
}
public IEnumerator<T> GetEnumerator()
{
return GetItems().GetEnumerator();
}
IEnumerator IEnumerable.GetEnumerator()
{
return GetEnumerator();
}
}
// Generic type leverage and extension invoking
public static class DepthAware
{
public static DepthAware<T> AsDepthAware<T>(this IEnumerable<T> source)
{
return new DepthAware<T>(source);
}
public static DepthAware<T> New<T>(IEnumerable<T> source)
{
return new DepthAware<T>(source);
}
}
Usage:
var chars = new[] {'a', 'b', 'c', 'd', 'e', 'f', 'g'}.AsDepthAware();
foreach (var item in chars)
{
Console.WriteLine("Char: {0}, depth: {1}", item, chars.Depth);
}
Cela dépend de la classe que vous utilisez.
Dictionary <(Of <(TKey, TValue>)>) Classe pour l'exemple prend en charge cette
La classe générique Dictionary <(Of <(TKey, TValue>)>) fournit un mappage d'un ensemble de clés à un ensemble de valeurs.
Aux fins de l'énumération, chaque élément du dictionnaire est traité comme une structure KeyValuePair <(Of <(TKey, TValue>)>) représentant une valeur et sa clé. L'ordre dans lequel les articles sont retournés est indéfini.
foreach (KeyValuePair kvp dans myDictionary) {...}