2012-11-29 46 views
0

如何將List <string>轉換爲Dictionary<string, int>如何將一個列表<string>轉換爲字典<string, int>?

這應該是從零到n的數字。

+1

什麼是'o'和什麼是'n'? – horgh

+0

@凱撒,編輯已經制定,指定「字典」。這是你真正需要的嗎?或者它是'詞典'?在我的答案中,'int'計數器是關鍵,這是不正確的每編輯... –

+0

@ Jonathon Reinhart ...是的,我只是指出了..然後如何你的代碼填充問題需要嗎? – FSm

回答

5

您可以使用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++); 

拉姆達傳遞給ToDictionarykeySelector。通常你用這個來select來自IEnumerable中的項目的一個屬性是關鍵,但在這裏,我們用它來提供一個計數。

編輯:第二個版本使用兩個選擇器。首先是關鍵。通過提供x => x lambda,我們只是使用來自列表的字符串。第二個選擇器是值。在這裏,我們正在提供計數器,i


性能

我決定測試一下我的方法與PST的方法的性能。

測試代碼:

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

輸出:

Jonathon's i++ method took 3005 ms 
pst's Select() method took 5019 ms 

輸出(後問題編輯):

Jonathon's i++ method took 3521 ms 
pst's Select() method took 5103 ms 

總之,似乎有一個約40%的改善通過使用計數器而不是創建中間匿名類型的對象。

+0

+1:我甚至刪除了我的回答.... – horgh

+0

@KonstantinVasilcov你的解決方案是正確的,除了'IndexOf'電話很貴,當你真正需要的是一個計數器。 –

+0

我希望我可以upvote你多次。優秀答案 – Habib

4

假設每個項目映射到按鍵和和n表示源索引,則:

var dict = list 
    .Select((v, i) => new {v, i}) 
    .ToDictionary(p => p.v, p => p.i); 

我喜歡這種方法,因爲當臨時匿名類型是有點靠不住的,這是一個自我含有副作用的自由表達。

(如果源列表中有任何重複的項目,這將引發異常。)

+0

我喜歡這個,因爲它使用'Select()'提供的索引,但是我覺得像額外的對象創建(匿名類型),只是傳遞給'ToDictionary'使得它不值得。 –

+2

@JonathonReinhart當我有一個性能測試案例,那麼我會關心:)我處理的代碼非常少,「性能嚴重」,因爲我的運行時間通常由其他因素支配,所以我不會厭倦主題呢。 – 2012-11-29 05:49:57

+0

+1。如果你喜歡Tuple,你可以使用'Tuple.Create(v,i)'而不是'new {v,i}'(結果相同)。 –

相關問題