10

如何在维护键索引的同时迭代字典的键。我所做的是将一个foreach-loop 与一个局部变量合并,该变量i在循环的每一轮中增加一个。

这是我的有效代码:

public IterateOverMyDict()
{
    int i=-1;
    foreach (string key in myDict.Keys)
    {
        i++;
        Console.Write(i.ToString() + " : " + key);
    }
}

但是,使用局部变量似乎技术含量很低i。我想知道是否有一种方法我不必使用“额外”变量?不是说这是一个坏方法,但有更好的方法吗?

4

5 回答 5

27

没有“键的索引”这样的概念。您应该始终将 aDictionary<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>表示值及其键的结构。返回项目的顺序未定义。

编辑:如果您不喜欢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);
}
于 2013-05-02T15:15:25.463 回答
3

从技术上讲,关键是 a 中的索引Dictionary<TKey, TValue>。您不能保证以任何特定顺序获取项目,因此实际上没有要应用的数字索引。

于 2013-05-02T15:15:53.117 回答
1

并不真地。请注意,字典中的键在逻辑上不是“有序”的。他们没有索引。从字典的角度来看,没有第一个或最后一个键。您可以自己跟踪这是否是枚举器返回的第一个键,就像您正在做的那样,但是字典没有“给我第 5 个键”的概念,因此您不能使用for带有索引器的循环作为您可以使用列表或数组。

于 2013-05-02T15:16:10.093 回答
0

字典并不完全是列表、数组或向量。他们将这些结构更进一步。键可以是索引:

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]);
}

在这一点上,您可能错过了字典的大部分好处(类似于枚举,具有对键值快速排序的好处),并且像列表一样使用它。

于 2013-05-02T15:36:28.670 回答
-1

Select((Entry, Index) => new { Entry, Index }) 方法在这个问题的特定上下文中可能是最好的,但作为替代方案,System.Linq.Enumerable 现在允许您将字典转换为列表。像这样的东西会起作用:

var x = dictionary.ToList();
for (int y=0; y<x.Count; y++) Console.WriteLine(y + " = " + x[y].Key);

这两种方法各有利弊,具体取决于您要执行的操作。

于 2018-09-24T15:07:02.160 回答