合并列表
问题描述:
我有一个List<KeyValuePair<string, List<string>>
,所以数据看起来类似:合并列表
user1, [trigger1,trigger2,trigger3]
user2, [trigger1,trigger4]
user3, [trigger2,trigger3,trigger4]
user1, [trigger0,trigger4]
我想使这个Dictionary<string,List<string>>
,而是直接失败,因为会有重复的键。有没有办法在LINQ上动态合并附加值的内容(意味着如果用户1是键的两倍,将两个关联的Lists<>
合并在一起)?
答
您需要在Key
上对KVP进行分组,并使用SelectMany
将列表“拼合”。如果你不想重复,使用Distinct()
将其删除:
var res = list
.GroupBy(p => p.Key)
.ToDictionary(
g => g.Key
, g => g.SelectMany(p => p.Value).Distinct().ToList()
); // ^^^^^^^^^^
// Remove Distinct() if you would like to keep all items
答
一个GroupBy
会做的大部分工作,以使所有的分组项目的列表结合的和你做。 GroupBy
的结果包含一个枚举列表,所以我们必须使用SelectMany
来选择所有字符串项目并从中构建一个列表。
Dictionary<string, List<string>> d = l.GroupBy(k => k.Key)
.ToDictionary(k => k.Key
, k => k.SelectMany(s => s.Value).ToList()
);
答
您可以通过以下顺序的一系列链式LINQ查询做到这一点:
-
GroupBy()
- 这将创建每个单独的用户群,以避免出现问题创建字典时(即重复密钥)。 -
ToDictionary()
- 此方法将使用键和值绑定给定的一组数据,因为您已经有了键(通过先前的调用),您只需从每个组中获取值。 -
SelectMany()
- 这将选择您之前的组中的所有单个值,实质上是将每组用户中的所有项目合并到一个集合中。 -
Distinct()
- 这将应用在上一步中生成的字符串列表中,以删除任何重复项。如果你想允许重复,只需删除这一步。
实现这个看起来像下面的代码片段:
// Group the collections by user and then select the keys based on those users
var dictionary = list.GroupBy(l => l.Key)
.ToDictionary(
x => x.Key,
x => x.SelectMany(l => l.Value)
.Distinct()
.ToList()
);
例
// Example of your existing data
var list = new List<KeyValuePair<string, List<string>>>(){
new KeyValuePair<string,List<string>>("User 1", new List<string>(){ "trigger1" ,"trigger2", "trigger3" }),
new KeyValuePair<string,List<string>>("User 2", new List<string>(){ "trigger1" ,"trigger2" }),
new KeyValuePair<string,List<string>>("User 3", new List<string>(){ "trigger2" ,"trigger3", "trigger4" }),
new KeyValuePair<string,List<string>>("User 1", new List<string>(){ "trigger0" ,"trigger4" }),
};
// Group the collections by user and then select the keys based on those users
var dictionary = list.GroupBy(l => l.Key)
.ToDictionary(
x => x.Key,
x => x.SelectMany(l => l.Value)
.Distinct()
.ToList()
);
// Output each key with it's associated values
foreach(var key in dictionary.Keys)
{
Console.WriteLine("Key: " + key + ", Values: " + String.Join(",",dictionary[key].ToArray()));
}
// Example output
// Key: User 1, Values: trigger1,trigger2,trigger3,trigger0,trigger4
// Key: User 2, Values: trigger1,trigger2
// Key: User 3, Values: trigger2,trigger3,trigger4
答
试试这个:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Data;
namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{
List<KeyValuePair<string, List<string>>> myList = new List<KeyValuePair<string,List<string>>>() {
new KeyValuePair<string, List<string>>("user1", new List<string> { "trigger1","trigger2","trigger3"}),
new KeyValuePair<string, List<string>>("user2", new List<string> { "trigger1","trigger4"}),
new KeyValuePair<string, List<string>>("user3", new List<string> { "trigger2","trigger3","trigger4"}),
new KeyValuePair<string, List<string>>("user1", new List<string> { "trigger0","trigger4"})
};
Dictionary<string, List<string>> dict = myList
.GroupBy(x => x.Key, y => y)
.ToDictionary(x => x.Key, y => y.Select(z => z.Value).SelectMany(a => a).ToList());
}
}
}
看起来不错,但我不需要list1.Concat(列表2),因为我只有1名名单。 – FailedUnitTest
@FailedUnitTest我认为你的KVP来自不同的来源。谢谢! – dasblinkenlight