linq 将数组转换为字典,值作为项的索引,键作为项本身

4ioopgfo  于 2022-12-06  发布在  其他
关注(0)|答案(3)|浏览(166)

我有一个数组,比如-

arr[0] = "Name";
arr[1] = "Address";
arr[2] = "Phone";
...

我想创建一个Dictionary<string, int>,这样数组值将是字典键,字典值将是索引,这样我就可以通过在O(1)中查询列的名称来获得列的索引。我知道这应该相当简单,但我还是想不明白。
我试过-

Dictionary<string, int> myDict = arr.ToDictionary(x => x, x => indexOf(x))

然而,这返回-

{(Name, 0), (Address, 0), (Phone, 0),...}

我知道会发生这种情况,因为它存储的是第一次出现的索引,但这不是我想要做的。

41zrol4v

41zrol4v1#

您可以使用Select的多载,其中包含索引:

var dictionary = array.Select((value, index) => new { value, index })
                      .ToDictionary(pair => pair.value, pair => pair.index);

或者使用Enumerable.Range

var dictionary = Enumerable.Range(0, array.Length).ToDictionary(x => array[x]);

请注意,如果您尝试提供两个相等的键,ToDictionary将抛出异常。您应该仔细考虑数组中有两个相等值的可能性,以及在这种情况下您希望发生的情况。
不过,我很想手动执行此操作:

var dictionary = new Dictionary<string, int>();
for (int i = 0; i < array.Length; i++)
{
    dictionary[array[i]] = i;
}
cngwdvgl

cngwdvgl2#

另一种说法是:

var dictionary = arr.ToDictionary(x => Array.IndexOf(arr, x));
csga3l58

csga3l583#

我做了一些基准测试,因为在我的场景中,性能和分配很重要。

var dictionary = new Dictionary<T, int>(array.Length);
for (var i = 0; i < array.Length; i++)
    dictionary[array[i]] = i;

诀窍是设置初始容量以减少字典数据结构内部的重新分配。请参见下表以比较结果(越少越好,基线设置为@Jon Skeet第一个答案):
| 检查方法|比率|分配比率|
| - -|- -|- -|
| 预分配|零点二九|零点二十七分|
| 手动强制循环|零点四八|零点七三|
| Enumerable.Range |零点六三|零点七八|
| 选择(元组)|1.0个|零点七八|
| 选择(匿名类型)|1.0个|1.0个|

相关问题