Есть ли эквивалент С# для Python enumerate()
и Ruby each_with_index
?
Foreach с индексом
Ответ 1
Я держу этот метод расширения для этого:
public static void Each<T>(this IEnumerable<T> ie, Action<T, int> action)
{
var i = 0;
foreach (var e in ie) action(e, i++);
}
И используйте это так:
var strings = new List<string>();
strings.Each((str, n) =>
{
// hooray
});
Или чтобы разрешить break
-like:
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;
});
Ответ 2
Вы можете сделать следующее
foreach (var it in someCollection.Select((x, i) => new { Value = x, Index = i }) )
{
if (it.Index > SomeNumber) //
}
Это создаст значение анонимного типа для каждой записи в коллекции. У него будет два свойства
Value
: с исходным значением в коллекцииIndex
: с указателем в коллекции
Ответ 3
С# foreach не имеет встроенного индекса. Вам нужно будет добавить целое число вне цикла foreach и увеличивать его каждый раз.
int i = -1;
foreach (Widget w in widgets)
{
i++;
// do something
}
В качестве альтернативы вы можете использовать стандарт для цикла следующим образом:
for (int i = 0; i < widgets.Length; i++)
{
w = widgets[i];
// do something
}
Ответ 4
Мне нравится возможность использовать foreach, поэтому я сделал метод расширения и структуру:
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++;
}
}
и пример использования:
foreach (var ii in new string[] { "a", "b", "c" }.Enumerate())
{
Console.WriteLine(ii.item + ii.cnt);
}
Хорошо, что если вы используете синтаксис Python, вы все равно можете его использовать:
foreach (var ii in Enumerate(new string[] { "a", "b", "c" }))
Ответ 5
Помимо уже полученных ответов LINQ, у меня есть класс "SmartEnumerable", который позволяет вам получить индекс и "первый/последний" -ness. Это немного уродливо с точки зрения синтаксиса, но вы можете найти это полезным.
Вероятно, мы можем улучшить вывод типов, используя статический метод неуниверсального типа, и неявная типизация тоже поможет.
Ответ 6
Мое решение включает в себя простой класс Pair, который я создал для общей утилиты, и который по сути является тем же самым, что и класс framework KeyValuePair. Затем я создал пару функций расширения для IEnumerable, называемых Ordinate (из терминов теории множеств ordinal").
Эти функции возвратят для каждого элемента объект Pair, содержащий индекс, и сам элемент.
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));
}
Ответ 7
Нет, нет.
Как показали другие люди, существуют способы имитировать поведение Ruby. Но возможно иметь тип, который реализует IEnumerable, который не предоставляет индекс.
Ответ 8
Я просто вычислил интересное решение:
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);
}
}
Использование:
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);
}
Ответ 9
Это ваша коллекция
var values = new[] {6, 2, 8, 45, 9, 3, 0};
Сделайте диапазон индексов для этой коллекции
var indexes = Enumerable.Range(0, values.Length).ToList();
Используйте диапазон для итерации с индексом
indexes.ForEach(i => values[i] += i);
indexes.ForEach(i => Console.Write("[{0}] = {1}", i, values[i]));
Ответ 10
Это зависит от класса, который вы используете.
Словарь < (Of < (TKey, TValue > ) > ) Класс для примера Поддержка Это
Универсальный класс Dictionary < (Of < (TKey, TValue > ) > ) предоставляет отображение из набора ключей в набор значений.
Для целей перечисления каждый элемент словаря рассматривается как структура KeyValuePair < (Of < (TKey, TValue > ) > ), представляющая значение и его ключ. Порядок возврата элементов undefined.
foreach (KeyValuePair kvp в myDictionary) {...}