2017-02-22 71 views
0

我有一个简单的key,value格式的文件,每行一个。 e.g:为什么不是这个LINQ正确解析文件?

word1,filepath1 
word2,filepath2 
word3,filepath5 

我想一气呵成使用LINQ到读入Dictionary<string,string>这一点。文件中有一些重复项(第一部分 - 第一个字符串 - 是重复项)。在这种情况下,我可以放弃重复项。

这是我的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

*我如何检索组中的第一个值* - 正确命名的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() lambda中处理的组对象是枚举数组,而不是字符串。 g.ElementAt(0)不是一个字符串。这是串的第一阵列:

g.Key == "word1" 

然后g.ElementAt(0)是...

{ "word1", "filepath1" } 

所以你要g.ElementAt(0).ElementAt(1),或g.First()[0],或诸如此类的话。

在事后看来,这似乎很明显,但不幸的是只有在事后,对我来说。

我建议您在接受Matthew Whited的回答后,通过将分割线尽快转换为匿名对象来澄清代码。 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对,如果没有至少一个成员,它不会存在吗?谢谢!并感谢发现那个流浪'x'。 –

相关问题