合并KeyValue对列表

时间:2017-02-22 15:48:19

标签: c# linq merge

我有List<KeyValuePair<string, List<string>>,因此数据类似于:

user1, [trigger1,trigger2,trigger3]
user2, [trigger1,trigger4]
user3, [trigger2,trigger3,trigger4]
user1, [trigger0,trigger4]

我想将其设为Dictionary<string,List<string>>,但直接失败是因为会有重复的密钥。有没有办法在LINQ中动态合并附加值的内容(意味着如果有两个用户键作为键,将两个关联的Lists<>组合在一起)?

4 个答案:

答案 0 :(得分:3)

您需要在.item:hover img { -moz-transform: scale(2.0); -webkit-transform: scale(2.0); transform: scale(2.0); } 上对KVP进行分组,然后使用Key来&#34;展平&#34;清单。如果您不想要重复,请使用SelectMany删除它们:

Distinct()

答案 1 :(得分:1)

GroupBy将执行大部分工作,同时制作所有已分组项目的列表,您就完成了。 GroupBy的结果包含可列举的列表,因此我们必须使用SelectMany选择所有字符串项,并构建一个列表。

Dictionary<string, List<string>> d = l.GroupBy(k => k.Key)
                                      .ToDictionary( k => k.Key
                                                   , k => k.SelectMany(s => s.Value).ToList()
                                                   );

答案 2 :(得分:1)

您可以按以下顺序通过一系列链式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

你可以see an interactive version of this here

答案 3 :(得分:0)

试试这个:

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

        }
    }
}