如何使用Linq将n List <dictionary <string,string =“” >>合并到字典中

时间:2019-02-20 16:43:50

标签: c# entity-framework linq .net-core

我尝试使用linq将一列字典(动态)合并到一个给定对象的单个列表中,我看到了许多与此问题类似的问题,但是在他们的情况下,他们总是考虑已知数目的词典。

好吧,这是我的结构:

我有一个查询,返回的是这样的列表对象:

public class MyDto 
{
  public Dictionary<string, string> JsonDictionary { get; set; }
  public Guid SomeId1{ get; set; }
  public Guid SomeId2{ get; set; } 
}

使用linq我正在这样做:

var q = _uow.TableWithJson.GetAll()
         .Include(a=> a.TableId1)
         .Include(a=> a.TableAux)
             .ThenInclude(b=> b.TableId2)
         .Select(r => new MyDto
             {
                SomeId1 = r.tableId1.Id,
                SomeId2 = r.tableId2.Id,
                JsonDictionary = JsonConvert.DeserializeObject<Dictionary<string, string>>(r.JsonContent)
             });

最后,我得到这样的结果;

{
  SomeId1: xxxxx,
  SomeId2: yyyyy,
  JsonDictionary: [
    {key: key1, value: value 1}
    {key: key1, value: value 2}
    {key: key1, value: value 3}
    {key: key1, value: value 4}
  ],
},
{
  SomeId1: xxxxx,
  SomeId2: yyyyy,
  JsonDictionary: [
    {key: key4, value: value 4}
    {key: key5, value: value 5}
    {key: key6, value: value 6}
  ],
}, // many other objects with different ids and different dictionaries.

如您所见,在上面的代码片段中,两个对象的SomeId1和SomeId2相同。因此,在这种情况下,我想将这些对象组合在一起,将JsonContent字段合并为一个字典。

也尝试使用.GroupBy,但我无法将此jsonContent合并为一个聚合。

帮助!!!请! =)拥抱

2 个答案:

答案 0 :(得分:1)

如果您希望以这种方式进行操作,则可以使用此方法...但是,您没有提供如何使用相同的键但值不同的方法来处理与JsonDictionaries的冲突。在这种情况下,我只是覆盖了先前声明的值。如果您想要其他行为,则必须更改此设置。

IEnumerable<MyDto> list = new List<MyDto>(); // This is the stuff you parsed
var results = new Dictionary<Tuple<Guid, Guid>, MyDto>();

foreach (var item in list) {
    var key = new Tuple<Guid, Guid>(item.SomeId1, item.SomeId2);
    if (results.ContainsKey(key))
        foreach (var entry in item.JsonDictionary)
            results[key].JsonDictionary[entry.Key] = entry.Value;
    else results[key] = item;
}

list = results.Values;

更新:

如果您真的想要,我用Linq编写了它。它的效率很低,但是我想不出许多其他方法来轻松实现此目的。如果要提高效率,应该使用上面的示例。

var results = list
    .GroupBy(
        x => new Tuple<Guid, Guid>(x.SomeId1, x.SomeId2), 
        (x, y) => new MyDto {
                SomeId1 = x.Item1,
                SomeId2 = x.Item2,
                JsonDictionary = y
                    .SelectMany(z => z.JsonDictionary)
                    .ToLookup(z => z.Key, z => z.Value)
                    .ToDictionary(z => z.Key, z => z.First())
        });

答案 1 :(得分:0)

好主意,不确定是否可以在linq中完全完成。

// lets group all of our id's and I'm not going to use groupby because I'm not a fan.
var itemsById = new Dictionary<string, List<MyDto>>();
foreach(var item in q)
{
   if(itemsById.ContainsKey(item.SomeId))
   {
       itemsById[item.SomeId].Add(item);
   }
   else 
   {
      itemsById.Add(item.SomeId, new List<MyDto>());
      itemsById[item.SomeId].Add(item);
   } 
}

so now we have dictionary of all of items by their ID.

var finalizedDtos = new List<MyDto>();
foreach(var entry in items)
{
   var finalizedDto = new MyDto{ someId = entry.Key };
   foreach(var innerDictionary in entry.value.JsonDictionary)
   {
                    var finalizedDto = new MyDto {SomeId = entry.Key};
                    var allKeyValuePairs = entry.Value.SelectMany(c => c.JsonDictionary);
                    finalizedDto.JsonDictionary = allKeyValuePairs.ToDictionary(key => key.Key, value => value.Value);
                    finalizedDtos.Add(finalizedDto);
   }
}

并不是很多linq,但是对于嵌套结构,我无法提出更好的计划