2017-02-22 95 views
0

У меня есть файл с простым форматом key,value, по одному в каждой строке. например:Почему этот LINQ не обрабатывает файл правильно?

word1,filepath1 
word2,filepath2 
word3,filepath5 

Я пытаюсь прочитать в Dictionary<string,string> на одном дыхании с помощью LINQ. В файле есть несколько дубликатов (где первая часть - первая строка - это дубликат). В этом случае, я в порядке с удалением дубликатов.

Это мой LINQ, который не работает:

var indexes = File.ReadAllLines(indexFileName) 
    .Select(x => x.Split(',')) 
    .GroupBy(x=>x[0]) 
    .ToDictionary(x => x.Key, x => x.ElementAt(1)); 

ToDictionary часть сбивает с толку меня, как я могу получить первое значение из группы, и присвоить ему значение словаря?

Я получаю исключение System.ArgumentOutOfRangeException: 'Specified argument was out of the range of valid values.'.

+2

поэтому вышеуказанный код не работает, любые erros? –

+1

Похоже, что он не работает, как вы ожидаете этого. Что это дает вам? – krillgar

+3

* как получить первое значение из группы * - метод aptly с именем 'First()' будет моим выбором. –

ответ

2
var indexes = File.ReadAllLines(indexFileName) 
        .Select(x => x.Split(',')) 
        .GroupBy(x => x[0]) 
        .ToDictionary(x => x.Key, x => x.First()[1]); 
2

Таким образом, проблема заключается в том, что вы группируете массивы, а не строки. Поэтому объекты группы, с которыми вы работаете в лямбда ToDictionary(), - это перечисления массивов, а не строк. g.ElementAt(0) не является строкой. Это первый массив строк:

Когда

g.Key == "word1" 

затем g.ElementAt(0) является ...

{ "word1", "filepath1" } 

Так что вы хотите g.ElementAt(0).ElementAt(1) или g.First()[0], или что-то об этом.

Это кажется болезненно очевидным в ретроспективе, но, к сожалению, только задним числом, для меня.

Я бы предположил, что после того, как вы примете ответ Мэтью Уайти, вы проясните код, превратив разделенные строки в анонимные объекты, как только сможете. ElementAt(1) не сообщает много.

var indexes = 
    File.ReadAllLines(indexFileName) 
    .Where(s => !String.IsNullOrEmpty(s)) 
    .Select(x => x.Split(',')) 
    // Turn the array into something self-documenting 
    .Select(a => new { Word = a[0], Path = a[1] }) 
    .GroupBy(o => o.Word) 
    .ToDictionary(g => g.Key, g => g.First().Path) 
    ; 

Преобразование каждой строки объекта делает его легче для меня, чтобы думать, и Intellisense начинает играть в вашей команде, а также.

+2

Красиво сделано. Кроме того, это безопасно для первой группы, так как всегда будет хотя бы один член. –

+0

@DavidB Правильно, его бы не было, если бы не было хотя бы одного члена, не так ли? Благодаря! И спасибо за то, что заметили, что блуждающий «х». –