Получение ключа массива в цикле 'foreach' - PullRequest
26 голосов
/ 13 сентября 2008

Как получить ключ текущего элемента в цикле 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
    }
}

Ответы [ 9 ]

23 голосов
/ 13 сентября 2008

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

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

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

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. Избыток, если это все, что вам нужно, но удобно, если вы склонны много обрабатывать коллекцию.

20 голосов
/ 13 сентября 2008

Если вы хотите получить ключ (читай: индекс), вам придется использовать цикл 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]);
}

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

8 голосов
/ 09 сентября 2011

С 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

3 голосов
/ 13 сентября 2008

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

Foreach для итерации коллекции, которые реализуют IEnumerable. Это делает это путем вызова GetEnumerator на коллекцию, которая вернет перечислитель.

Этот перечислитель имеет метод и Свойство:

* MoveNext()
* Current

Current возвращает объект, который Перечислитель сейчас включен, MoveNext обновляет текущий до следующего объекта.

Очевидно, что понятие индекса чуждо концепции перечисления, и не может быть сделано.

Из-за этого большинство коллекций может быть пройден с помощью индексатора и конструкция цикла for.

Я очень предпочитаю использовать цикл for эта ситуация по сравнению с отслеживанием индекс с локальной переменной.

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

3 голосов
/ 13 сентября 2008

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

1 голос
/ 13 сентября 2008

На самом деле вы должны использовать классический цикл 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);
}
0 голосов
/ 31 декабря 2009

Вы можете реализовать эту функцию самостоятельно, используя метод расширения. Например, вот реализация метода расширения 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]);
    }
}
0 голосов
/ 31 декабря 2009

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

Оригинальный код:

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;
    }
0 голосов
/ 13 сентября 2008

myKey = Array.IndexOf(values, val);

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...