【问题标题】:Merge List of KeyValue Pairs合并键值对列表
【发布时间】:2017-02-22 15:48:19
【问题描述】:

我有一个List<KeyValuePair<string, List<string>>,所以数据看起来像:

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

我想将其设为Dictionary<string,List<string>>,但这直接失败了,因为会有重复的键。有没有办法在 LINQ 中即时合并附加值的内容(意思是如果有 user1 两次作为键,则组合两个关联的Lists<>)?

【问题讨论】:

    标签: c# linq merge


    【解决方案1】:

    您需要在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
    

    【讨论】:

    • 看起来不错,除了我不需要 list1.Concat(list2) 因为我只有 1 个列表。
    • @FailedUnitTest 我认为您的 KVP 来自不同的来源。谢谢!
    【解决方案2】:

    GroupBy 将完成大部分工作,结合列出所有分组项目的列表,您就完成了。 GroupBy 的结果包含一个可枚举的列表,因此我们必须使用 SelectMany 选择所有字符串项并从中构造一个列表。

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

    【讨论】:

      【解决方案3】:

      您可以按以下顺序通过一系列链式 LINQ 查询来完成此操作:

      • GroupBy() - 这将为您的每个用户创建组,以避免在创建字典时出现问题(即重复键)。
      • ToDictionary() - 此方法可以使用键和值绑定给定的数据集,因为您已经有了键(通过之前的调用),您只需要从每个组。
      • SelectMany() - 这将从您之前的组中选择所有单独的值,实质上是将每组用户的所有项目合并到一个集合中。
      • Distinct() - 这将应用于上一步中生成的字符串列表以删除任何重复项。如果您想允许重复,只需删除此步骤即可。

      实现这一点类似于以下 sn-p 代码:

      // 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

      【讨论】:

        【解决方案4】:

        试试这个:

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

        【讨论】:

          猜你喜欢
          • 2022-12-18
          • 2017-03-23
          • 2017-10-26
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2021-09-17
          • 1970-01-01
          相关资源
          最近更新 更多