Получение ключа массива в цикле foreach

Как получить ключ текущего элемента в цикле foreach в C#?

Например:

PHP

foreach ($array as $key => $value)
{
    echo("$value is assigned to key: $key");
}

Что я пытаюсь сделать на C#:

int[] values = { 5, 14, 29, 49, 99, 150, 999 };

foreach (int val in values)
{
    if (search <= val && !stop)
    {
         // Set key to a variable
    }
}
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
27
0
84 074
9
Перейти к ответу Данный вопрос помечен как решенный

Ответы 9

Увы, встроенного способа сделать это нет. Либо используйте цикл for, либо создайте временную переменную, которая увеличивается на каждом проходе.

myKey = Array.IndexOf(values, val);

Это плохая идея. Array.IndexOf - это в основном поиск с худшим случаем O (n). Сделайте это n раз, ваш общий худший случай станет O (n ^ 2). С точки зрения непрофессионала, массив из 100 элементов может потребовать до 10000 сравнений.

Jonathan Allen 13.09.2008 02:21

Помимо эффективности, если в массиве есть повторяющиеся элементы, вы получите индекс первого, не обязательно того, который вы используете. Рассмотрим массив из {5, 14, 5, 29, ...}. Когда val равно 5, вы всегда получите ноль, даже если вы находитесь на третьем элементе.

Andrew 13.09.2008 02:33

Если вы хотите получить ключ (читайте: индекс), вам придется использовать цикл for. Если вы действительно хотите иметь коллекцию, содержащую ключи / значения, я бы подумал об использовании HashTable или Dictionary (если вы хотите использовать Generics).

Dictionary<int, string> items = new  Dictionary<int, string>();

foreach (int key in items.Keys)
{
  Console.WriteLine("Key: {0} has value: {1}", key, items[key]);
}

Надеюсь, это поможет, Тайлер

Было бы намного эффективнее выполнить foreach (пара KeyValuePair <int, string> в элементах), а затем ссылаться на pair.Key и pair.Value, а не выполнять поиск на каждой итерации.

Chris Ammerman 13.09.2008 02:38

На самом деле вам следует использовать классический цикл for (;;), если вы хотите перебирать массив. Но аналогичная функциональность, которую вы достигли с помощью своего PHP-кода, может быть достигнута на C#, например, с помощью словаря:

Dictionary<int, int> values = new Dictionary<int, int>();
values[0] = 5;
values[1] = 14;
values[2] = 29;
values[3] = 49;
// whatever...

foreach (int key in values.Keys)
{
    Console.WriteLine("{0} is assigned to key: {1}", values[key], key);
}

Было бы гораздо эффективнее выполнить foreach (пара KeyValuePair <int, int> в значениях), а затем ссылаться на pair.Key и pair.Value, а не выполнять поиск на каждой итерации.

Chris Ammerman 13.09.2008 02:39
Ответ принят как подходящий

Путь Грауэнвольфа - самый простой и эффективный способ сделать это с массивом:

Either use a for loop or create a temp variable that you increment on each pass.

Что, конечно, выглядело бы так:

int[] values = { 5, 14, 29, 49, 99, 150, 999 };

for (int key = 0; key < values.Length; ++key)
  if (search <= values[key] && !stop)
  {
    // set key to a variable
  }

С .NET 3.5 вы также можете использовать более функциональный подход, но он немного более подробный на сайте и, вероятно, будет полагаться на пару вспомогательные функции для посещение элементов в IEnumerable. Излишний, если это все, что вам нужно, но удобно, если вы склонны выполнять большую часть обработки коллекции.

"или создайте временную переменную, которую вы увеличиваете на каждом проходе" as far as I remember, there is no guarantee that foreach will loop over your collection in an ascending (or descending) order, only that it will stop at every element at ровно один раз, therefor if you are using an external value, your solution might- or might not be valid based on the implementation. Normally it will give you the desired result, but i.e. a common optimization is to parse an array in descending order (it takes one less machine instruction than ascending order per cycle).
mg30rg 31.10.2017 13:38

Я думаю, это зависит от типа перечисляемого, который вы повторяете. Если это массив, я думаю, порядок будет гарантирован.

Kyle Delaney 05.12.2017 05:55

Я ответил на это в другой версии этого вопроса:

Foreach is for iterating over collections that implement IEnumerable. It does this by calling GetEnumerator on the collection, which will return an Enumerator.

This Enumerator has a method and a property:

* MoveNext()
* Current

Current returns the object that Enumerator is currently on, MoveNext updates Current to the next object.

Obviously, the concept of an index is foreign to the concept of enumeration, and cannot be done.

Because of that, most collections are able to be traversed using an indexer and the for loop construct.

I greatly prefer using a for loop in this situation compared to tracking the index with a local variable.

Как получить индекс текущей итерации цикла foreach?

Вот решение, которое я только что придумал для этой проблемы

Исходный код:

int index=0;
foreach (var item in enumerable)
{
    blah(item, index); // some code that depends on the index
    index++;
}

Обновленный код

enumerable.ForEach((item, index) => blah(item, index));

Метод расширения:

    public static IEnumerable<T> ForEach<T>(this IEnumerable<T> enumerable, Action<T, int> action)
    {
        var unit = new Unit(); // unit is a new type from the reactive framework (http://msdn.microsoft.com/en-us/devlabs/ee794896.aspx) to represent a void, since in C# you can't return a void
        enumerable.Select((item, i) => 
            {
                action(item, i);
                return unit;
            }).ToList();

        return pSource;
    }

Вы можете реализовать эту функцию самостоятельно, используя метод расширения. Например, вот реализация метода расширения KeyValuePairs, который работает со списками:

public struct IndexValue<T> {
    public int Index {get; private set;}
    public T Value {get; private set;}
    public IndexValue(int index, T value) : this() {
        this.Index = index;
        this.Value = value;
    }
}

public static class EnumExtension
{
    public static IEnumerable<IndexValue<T>> KeyValuePairs<T>(this IList<T> list) {
        for (int i = 0; i < list.Count; i++)
            yield return new IndexValue<T>(i, list[i]);
    }
}

С помощью DictionaryEntry и KeyValuePair:

На основе
MSDN

IDictionary<string,string> openWith = new Dictionary<string,string>()
{
   { "txt", "notepad.exe" }
   { "bmp", "paint.exe" }
   { "rtf", "wordpad.exe" }
};

foreach (DictionaryEntry de in openWith)
{
    Console.WriteLine("Key = {0}, Value = {1}", de.Key, de.Value);
}

// also

foreach (KeyValuePair<string,string> de in openWith)
{
    Console.WriteLine("Key = {0}, Value = {1}", de.Key, de.Value);
}

Повторный вопрос SO: KeyValuePair VS DictionaryEntry

Другие вопросы по теме