2012-12-12 23 views
2

我想採用List,並生成一個Dictionary,它將每個元素映射到List中的索引。我能做到這一點,像這樣,對於一個List<string>使用Linq生成列表元素索引的地圖

var myList = new List<string>{ /* populate list */ }; 
var orderMap = new Dictionary<string, int>(); 

foreach (var element in myList) 
{ 
    orderMap[element] = myList.IndexOf(element); 
} 

基本上,我想帶像一個列表:

Apple 
Banana 
Orange 

,並返回一個地圖,顯示指數:

Apple -> 0 
Banana -> 1 
Orange -> 2 

如何我可以用Linq做這個嗎?我覺得這樣的事情應該工作:

orderMap = myList.Select(x => /* return a key value pair mapping x to myList.IndexOf(x) */); 

但我不能找出正確的語法它。此外,您是否可以參考用於Select的代表列表本身?

回答

6

雖然你可以引用委託中的列表,它通常不是一個好主意。你真的想用Select過載提供索引以及價值:

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

請注意,如果您有任何重複的元素,這將拋出一個異常。

3

你可以嘗試ToDictionary擴展方法:

int index = 0; 
orderMap = myList.ToDictionary(x => x, x => index++); 
+2

Ick,在選擇器中的副作用?不,謝謝:)我意識到,在這種情況下,它使用即時評估,*將*工作 - 但它仍然是我個人避免的東西。 –

+0

這將選擇索引作爲關鍵字,但OP要將該字符串作爲關鍵字。 –

+0

@JonSkeet我知道這不是最乾淨的解決方案。我似乎總是忘記'Select'的有用重載:) @ L.B謝謝,修正了這個問題。誤解了這個問題。 – Botz3000

0

看看this overload of ToDictionary<TKey, TValue>()。它需要將輸入元素轉換爲Key和Value的函數。

例如

var myList = new List<string>{ /* populate list */ }; 
var orderMap = myList.ToDictionary(x => myList.IndexOf(x), x => x); 

然而,一個問題是,如果的myList元素是不是唯一的。

+0

這將在O(n^2 * log(n))中運行,而另外兩個答案在O(n * log(n))中運行,因爲'IndexOf()'將掃描列表。 –