2017-02-22 11 views
1

У меня есть List<KeyValuePair<string, List<string>>, поэтому данные выглядит примерно так:Merge Список KeyValue пара

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

Я хотел бы сделать это Dictionary<string,List<string>>, но сразу это не удается, потому что будут дублированные ключи. Есть ли способ объединить содержимое прикрепленных значений «на лету» (что означает, что если пользователь 1 дважды в качестве ключей, объедините два связанных Lists<>) в LINQ?

ответ

3

Вам необходимо сгруппировать KVP на Key и использовать 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 
+0

Выглядит хорошо, за исключением того, мне не нужно list1.Concat (песни2), так как у меня только 1 список. – FailedUnitTest

+0

@FailedUnitTest Я думал, что ваши КВП происходят из разных источников. Благодаря! – dasblinkenlight

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

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

     } 
    } 
} 
Смежные вопросы