使用Linq将List<string>转换为List<KeyValuePair<string, string>>

11
假设我有以下的List<string>

可能重复:
是否有一种LINQ方式将键值对列表转换为字典?

请注意,以下是需要翻译的内容:

var input = new List<string>()
                       {
                           "key1",
                           "value1",
                           "key2",
                           "value2",
                           "key3",
                           "value3",
                           "key4",
                           "value4"
                       };

根据这个列表,我希望转换成 List<KeyValuePair<string, string>>,原因是为了允许相同的key,这就是为什么我不使用Dictionary。

var output = new List<KeyValuePair<string, string>>()
                       {
                           new KeyValuePair<string, string>("key1", "value1"),
                           new KeyValuePair<string, string>("key2", "value2"),
                           new KeyValuePair<string, string>("key3", "value3"),
                           new KeyValuePair<string, string>("key4", "value4"),
                       };

我可以使用以下代码实现:
var keys = new List<string>();
var values = new List<string>();

for (int index = 0; index < input.Count; index++)
{
    if (index % 2 == 0) keys.Add(input[index]);
    else values.Add(input[index]);
}

var result = keys.Zip(values, (key, value) => 
                        new KeyValuePair<string, string>(key, value));

但是感觉使用 for 循环不是最好的方式,有没有另一种方法可以使用内置的 LINQ 来实现呢?


5
"LINQ原则 #1": 除非您能在3分钟内自己编写LINQ查询,否则不值得使用它。请使用简单的for循环。 - Euphoric
4个回答

11
var output = Enumerable.Range(0, input.Count / 2)
                       .Select(i => Tuple.Create(input[i * 2], input[i * 2 + 1]))
                       .ToList();

请执行以下代码 var output = Enumerable.Range(0, input.Count / 2).Select(i => new KeyValuePair<string, string>(input[i * 2], input[i * 2 + 1])).ToList();,因为 OP 需要一个 KeyValuePair。 - Nikhil Agrawal
是的,我知道,但这并不重要,因为KeyValuePair与Tuple有点相似。 - cuongle

7

我不建议在这里使用LINQ,因为没有什么理由使用它,并且使用LINQ并不能带来任何好处,而是应该使用普通的for循环,每次迭代将计数变量增加两个:

var result = new List<KeyValuePair<string, string>>();

for (int index = 1; index < input.Count; index += 2)
{
    result.Add(new KeyValuePair<string, string>(input[index - 1], input[index]));
}

请注意,我将索引从 1 开始,这样就不会遇到访问无效索引的异常,在input中项目数量是奇数的情况下,也就是当input以“半对”值结束时。


4
你可以使用这个:
IEnumerable<KeyValuePair<string, string>> list = 
        input.Where((s, i) => i % 2 == 0)
             .Select((s, i) => new KeyValuePair<string, string>(s, input.ElementAt(i * 2 + 1)));

那也是不错的 Linq :) - cuongle
很高兴听到这个消息,虽然我感觉自己的答案太相似了,哎呀) - horgh

0
你可以使用LINQ的Aggregate()函数(代码比简单循环长):
var result = 
input.Aggregate(new List<List<string>>(),
                (acc, s) =>
                {
                    if (acc.Count == 0 || acc[acc.Count - 1].Count == 2)
                        acc.Add(new List<string>(2) { s });
                    else
                        acc[acc.Count - 1].Add(s);
                    return acc;
                })
                .Select(x => new KeyValuePair<string, string>(x[0], x[1]))
                .ToList();

注意:
即使您的初始输入变成通用的 IEnumerable<string> 而不是特定的 List<string>,此方法仍然有效。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接