2009-09-10 69 views
3

我試圖使用LINQ To Objects來創建一個查詢,該查詢將爲我提供按文件名索引的文件,並將映射到其二進制數據的值映射爲byte[]創建使用LINQ到對象的鍵/值集合

但是我找不到一個'整潔'的方式來做到這一點。我希望能得到類似Dictionary<T,K>的輸出。

這是我到目前爲止。例如delimFileNames =「1.JPG | 2.JPG」

//Extract filenames from filename string 
//and read file binary from file 
//select result into a filename indexed collection 
var result = from f in delimFileNames.Split(Constants.DDS_FILENAME_SEPARATOR) 
      let filePath = Path.Combine(ddsClient.WorkingDirectory, f) 
      let fileData = File.ReadAllBytes(filePath) 
      select new KeyValuePair<string, byte[]>(f, fileData); 

return result.ToDictionary(kvp => kvp.Key, kvp=> kvp.Value); 

主要摸不到頭腦就是爲什麼我不能用一個無參數ToDictionary(),或直接投。任何建議或替代方案來改善上述讚賞。

回答

5

ToDictionary()就必須有鍵值對特殊情況 - 你可以添加的,當然你自己的擴展方法:

public static Dictionary<TKey, TValue> ToDictionary<TKey, TValue>(
    IEnumerable<KeyValuePair<TKey, TValue>> source) 
{ 
    return source.ToDictionary(kvp => kvp.Key, kvp=> kvp.Value); 
} 

沒有這種擴展方法,你可以做這樣的:

var result = from f in delimFileNames.Split(Constants.DDS_FILENAME_SEPARATOR) 
            .ToDictionary(f => f, 
      // Outdented to avoid scrolling 
      f => File.ReadAllBytes(Path.Combine(ddsClient.WorkingDirectory, f)); 

基本上查詢表達式允許你做所有時髦的「讓」東西,但是強制你在最後有一個select,這使得你可以將兩個不同的值(鍵和字節數組)傳播到兩個屬性中。

+0

+1我想你潛伏在等待着這些問題喬恩:P – 2009-09-10 13:58:32

2

「主要摸不到頭腦就是爲什麼我不能用一個無參數ToDictionary()[...]」

因爲ToDictionary方法需要知道什麼是重點,什麼是價值。微軟可能已經爲這個特例創建了一個重載,但是沒有,因爲我認爲這個好處並不是很大。但是沒有什麼能阻止你創建你自己的擴展方法。

「或直接投射。」

因爲你的LINQ查詢返回的IEnumerable<KeyValuePair<TKey, TValue>>這不是Dictionary<TKey, TValue>。它允許您枚舉鍵/值對,但不允許通過鍵快速查找。

請注意,儘管Dictionary<TKey, TValue>IEnumerable<KeyValuePair<TKey, TValue>>(它實現了該接口),這意味着您可以像使用Linq查詢一樣遍歷鍵/值對,但底層類型是Dictionary,所以您可以通過鍵快速查找。

1

你並不需要使用KeyValuePair<,>,而是你可以使用匿名類型,它允許你KeyValue使用更具描述性的名字比:

var files = 
    from fileName in delimFileNames.Split(Constants.DDS_FILENAME_SEPARATOR) 
    let filePath = Path.Combine(ddsClient.WorkingDirectory, fileName) 
    select new 
    { 
     Path = filePath, 
     Data = File.ReadAllBytes(filePath) 
    }; 

return files.ToDictionary(file => file.Path, file => file.Data);