[英]How can I transform a List <string> to a Dictionary<string, int>?
How can I transform a List <string>
to a Dictionary<string, int>
? 如何将
List <string>
转换为Dictionary<string, int>
?
This should be number from zero to n. 这应该是从零到n的数字。
You can use ToDictionary()
to create a Dictionary
from any IEnumerable
. 您可以使用
ToDictionary()
从任何IEnumerable
创建Dictionary
。
var list = new List<string>() { "Foo", "Bar", "Spam" };
// TKey is int, TValue is string
int i = 0;
Dictionary<int,string> dict1 = list.ToDictionary( _ => i++ );
// TKey is string, TValue is int
i = 0;
Dictionary<string,int> dict2 = list.ToDictionary( x => x, _ => i++ );
The lambda passed to ToDictionary
is the keySelector
. 传递给
ToDictionary
的lambda是keySelector
。 Usually you use this to select a property from the items in the IEnumerable
to be the key, but here, we use it to provide a count. 通常,您可以使用它从
IEnumerable
的项中选择一个属性作为键,但是在这里,我们使用它来提供计数。
Edit: The second version uses two selectors. 编辑:第二个版本使用两个选择器。 The first is the key.
首先是关键。 By providing a
x => x
lambda, we are just using the string that came from the list. 通过提供
x => x
lambda,我们仅使用了来自列表的字符串。 The second selector is the value. 第二个选择器是值。 Here, we are providing the counter,
i
. 在这里,我们提供柜台
i
。
Performance 性能
I decided to test out the performance of my method versus pst's method. 我决定测试我的方法与pst方法的性能。
Test Code: 测试代码:
static void Main(string[] args) {
const int N = 1000000;
const int M = 10;
Stopwatch s;
// Generate test list of strings.
var list = Enumerable.Range(0, N).Select(n => n.ToString());
// Just so it's enumerated once before.
var ar = list.ToArray();
// Try Jonathon's method M times.
s = Stopwatch.StartNew();
for (int x = 0; x < M; x++) {
int i = 0;
//var dict1 = list.ToDictionary(_ => i++); // Before question edit
var dict1 = list.ToDictionary(x => x, _ => i++);
}
s.Stop();
Console.WriteLine("Jonathon's i++ method took {0} ms", s.ElapsedMilliseconds);
// Try pst's method M times.
s = Stopwatch.StartNew();
for (int x = 0; x < M; x++) {
var dict2 = list.Select((v, j) => new {v, j}).ToDictionary(p => p.v, p => p.j);
}
s.Stop();
Console.WriteLine("psts' Select() method took {0} ms", s.ElapsedMilliseconds);
Console.ReadLine();
}
Output: 输出:
Jonathon's i++ method took 3005 ms
pst's Select() method took 5019 ms
Output (After question edit): 输出(问题编辑后):
Jonathon's i++ method took 3521 ms
pst's Select() method took 5103 ms
In conclusion, it appears that there is a roughly 40% improvement by using a counter instead of creating the intermediate, anonymous-typed objects. 总之,通过使用计数器而不是创建中间的匿名类型的对象,似乎可以将大约40%的性能提高。
Assuming that each item maps to the key and and n
represents the index in the source, then: 假设每个项目都映射到键,并且
n
代表源中的索引,则:
var dict = list
.Select((v, i) => new {v, i})
.ToDictionary(p => p.v, p => p.i);
I like this approach because, while the temporary anonymous type is a little wonky, it's a self-contained side-effect free expression. 我喜欢这种方法,因为,尽管临时匿名类型有些古怪,但它是一个自包含的副作用免费表达式。
(This will throw an exception if there are any duplicate items in the source list.) (如果源列表中有任何重复项,则将引发异常。)
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.