Как разобрать два списка в словарь, где свойство id в обоих становится ключом?

#c# #linq #dictionary

Вопрос:

Кажется, мне трудно найти простой способ вставить мою старую и новую регистрацию в словарь, отформатированный как

 Dictionary<int, List<Registration>, List<Registration>>
 

Где первый список содержит старую регистрацию, а другой содержит новую регистрацию.
У них есть идентификатор в commmon, который должен быть ключом, и если это не так, то другой список должен быть пустым.

Кажется, мне трудно найти оператор Linq, способный сделать это, я бы предположил, что это была работа для GroupBy или GroupJoin, но не могу понять, как это должно выглядеть..

MVC: https://dotnetfiddle.net/BIbPqY

 using System;
using System.Collections.Generic;

    
public class Program
{
    public static void Main()
    {
        Dictionary<string, object> openWith =
                new Dictionary<string, object>();
        openWith.Add("txt", "notepad.exe");
        openWith.Add("bmp", "paint.exe");
        openWith.Add("dib", "paint.exe");
        openWith.Add("rtf", "wordpad.exe");
        
        Registration reg1 = new Registration()
        {
            id = 1,
            attributes = openWith
        };
    
        Registration reg2 = new Registration()
        {
            id = 2,
            attributes = openWith
        };

        Registration reg3 = new Registration()
        {
            id = 1,
            attributes = openWith
        };
        
        Registration reg4 = new Registration()
        {
            id = 2,
            attributes = openWith
        };
        
        List<Registration> oldReg = new List<Registration>() {reg1, reg2 }; 
        List<Registration> newReg = new List<Registration>() {reg3, reg4 };
        
        Console.WriteLine("Hellow World");
    }
    
    public class Registration
    {
        public int id {get; set;}
        public Dictionary<string, object> attributes {get; set;}
    }
}
 

Мой текущий способ обработки — создать два словаря с помощью groupBy

 Dictionary<int, List<Registration>> oldRegDic = 
        oldReg.GroupBy(o => o.id).ToDictionary(g => g.Key, g => g.ToList());
Dictionary<int, List<Registration>> newRegDic = 
        newReg.GroupBy(o => o.id).ToDictionary(g => g.Key, g => g.ToList());

        Dictionary<int, (List<Registration>, List<Registration>)> oldAndNewRegistrationDictionary = new();

        foreach (KeyValuePair<int, List<Registration>> newReg in newRegistrationDictionary)
        {
            (List<EntityRegistration>, List<EntityRegistration>) oldNewPair = new()
            {
                Item1 = oldRegDic[newReg.Key], Item2 = newRegDic[newReg.Key]
            };
        }
 

А затем перебрать их оба и добавить их в новый словарь, но это выглядит очень неэффективно.

Комментарии:

1. Dictionary<int, List<Registration>, List<Registration>> не имеет смысла. Dictionary<TKey, TValue> принимает только два параметра общего типа. Может быть, вы намеревались создать класс, в котором есть оба списка? class Foo { public List<Registration> list1, list2; } а потом есть Dictionary <int, Foo> ?

2. это было сделано для того, чтобы избежать создания для него целого класса, но я понимаю вашу точку зрения

Ответ №1:

Здесь хорошо иметь полное соединение, но его можно эмулировать двумя запросами:

 var query1 = 
    from n in newReg
    join o in oldReg on n.id equals o.id into gj
    from o in gj.DefaultIfEmpty()
    select new { id = n.id, n, o };

var query2 = 
    from o in oldReg
    join n in newReg on o.id equals n.id into gj
    from n in gj.DefaultIfEmpty()
    where n == null
    select new { id = o.id, n, o };

var result = query1.Concat(query2)
    .ToDictionary(x => x.id, x => Tuple.Create(x.o, x.n));