我尝试使用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合并为一个聚合。
帮助!!!请! =)拥抱
答案 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,但是对于嵌套结构,我无法提出更好的计划