Создание коллекций Key / Value с использованием LINQ To Objects - PullRequest
3 голосов
/ 10 сентября 2009

Я пытаюсь использовать LINQ To Objects для создания запроса, который даст мне файлы, проиндексированные по имени файла со значением, сопоставленным с их двоичными данными как byte[].

Однако я не могу найти «аккуратный» способ сделать это. Я надеюсь получить что-то вроде 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 () без параметров или прямое приведение. Будем благодарны за любые предложения или альтернативы по улучшению вышеперечисленного.

Ответы [ 3 ]

5 голосов
/ 10 сентября 2009

ToDictionary() должен был бы иметь специальный случай для KeyValuePair - который вы, конечно, можете добавить в качестве собственного метода расширения:

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, что позволяет вам распространять два разных значения (ключ и байтовый массив) на два свойства.

2 голосов
/ 10 сентября 2009

"Главный скребок головы - это то, почему я не могу использовать ToDictionary () [...]" без параметров *

Потому что метод ToDictionary должен знать, что является ключом и каково значение. Microsoft могла бы создать перегрузку для этого особого случая, но не сделала этого, потому что, я полагаю, выгода не очень большая. Но ничто не мешает вам создать собственный метод расширения, который делает именно это.

"[...] или прямое приведение."

Поскольку ваш запрос Linq возвращает IEnumerable<KeyValuePair<TKey, TValue>>, который не является Dictionary<TKey, TValue>. Он позволяет вам перечислять пары ключ / значение, но не позволяет осуществлять быстрый поиск по ключу.

Обратите внимание, что Dictionary<TKey, TValue> - это IEnumerable<KeyValuePair<TKey, TValue>>, хотя (он реализует этот интерфейс), что означает, что вы можете перебирать пары ключ / значение так же, как вы делали с запросом Linq, но базовый тип - это Словарь , так что вы можете получить быстрый поиск по ключу.

1 голос
/ 10 сентября 2009

Вам не нужно использовать KeyValuePair<,>, вместо этого вы можете использовать анонимный тип, который позволяет использовать больше описательных имен, чем Key и Value:

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);
...