Перебирать ключи словаря C# с индексом?
Как выполнить итерацию по ключам словаря при сохранении индекса ключа.
Что я сделал слияние foreach
- цикл с локальной переменной i
, который увеличивается на единицу для каждого витка цикла.
вот мой код, который работает:
public IterateOverMyDict()
{
int i=-1;
foreach (string key in myDict.Keys)
{
i++;
Console.Write(i.ToString() + " : " + key);
}
}
однако использование локальной переменной i
.
Мне было интересно, есть ли способ, когда мне не нужно использовать "дополнительную" переменную?
Не говоря, что это плохой путь, но есть ли лучший? один?
5 ответов
нет такого понятия, как "индекс ключа". Вы всегда должны лечить Dictionary<TKey, TValue>
как имеющий непредсказуемый порядок-где порядок, который вы чтобы получить при итерации по нему может измениться. (Таким образом, теоретически, вы можете добавить одну новую запись,и записи могут быть в совершенно другом порядке в следующий раз, когда вы повторите их. Теоретически это может даже произойти без вы меняете данные, но это менее вероятно в нормальных реализации.)
если вы действительно хотите получить числовой индекс, который вы наблюдали на этот раз, вы можете использовать:
foreach (var x in dictionary.Select((Entry, Index) => new { Entry, Index }))
{
Console.WriteLine("{0}: {1} = {2}", x.Index, x.Entry.Key, x.Entry.Value);
}
... но имейте в виду, что это довольно вводящий в заблуждение дисплей, поскольку он предполагает неотъемлемый порядок.
С документация:
для целей перечисления, каждый элемент в словаре трактуется как
KeyValuePair<TKey, TValue>
структура, представляющая значение и его ключ. Этот порядок, в котором возвращается неопределено.
EDIT: Если вам не нравится Select
звони сюда, ты мог бы создать свой собственный метод расширения:
public struct IndexedValue<T>
{
private readonly T value;
private readonly int index;
public T Value { get { return value; } }
public int Index { get { return index; } }
public IndexedValue(T value, int index)
{
this.value = value;
this.index = index;
}
}
public static class Extensions
{
public static IEnumerable<IndexedValue<T>> WithIndex<T>
(this IEnumerable<T> source)
{
return source.Select((value, index) => new IndexedValue<T>(value, index));
}
}
тогда ваш цикл будет:
foreach (var x in dictionary.WithIndex())
{
Console.WriteLine("{0}: {1} = {2}", x.Index, x.Value.Key, x.Value.Value);
}
технически ключом является индекс в Dictionary<TKey, TValue>
. Вы не гарантированно получите элементы в определенном порядке, поэтому на самом деле нет никакого числового индекса.
Не совсем так. Обратите внимание, что ключи в словаре не являются логически "упорядоченными". У них нет указателя. С точки зрения словаря, нет ни первого, ни последнего ключа. Вы можете самостоятельно отслеживать, является ли это первым ключом, возвращаемым перечислителем, как вы это делаете, но в словаре нет понятия "дайте мне 5-й ключ", поэтому вы не можете использовать for
цикл с индексатором, как вы могли бы со списком или массивом.
словари не совсем списки, массивы или векторы. Они делают еще один шаг вперед. Ключом может быть индекс:
Dictionary myDictionary<int, string> = new Dictionary<int, string>()
{
{0, "cat"},
{1, "dog"},
{2, "pig"},
{3, "horse"}
};
myDictionary[4] = "hat";
for int i = 0; i <5; i++){
Console.Writeline(myDictionary[i]);
}
на данный момент вам, вероятно, не хватает большинства преимуществ словаря (который похож на перечисление с преимуществом быстрой сортировки по ключевым значениям) и использует его как список.
подход Select((Entry, Index) => new { Entry, Index}), вероятно, лучше всего в конкретном контексте этого вопроса, но, как альтернатива, система.В LINQ.Enumerable теперь позволяет конвертировать словарь в список. Что-то вроде этого сработает:
var x = dictionary.ToList();
for (int y=0; y<x.Count; y++) Console.WriteLine(y + " = " + x[y].Key);
есть плюсы и минусы обоих подходов, в зависимости от того, что вы пытаетесь сделать.