Я попытался объединить список (динамический) словарей в один список для данного объекта, используя 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 как агрегацию.
Помощь!!! Пожалуйста! =) Объятия
Возможно, вы сможете сделать что-то подобное, переопределив HashSet и определив свой someid как ключ, который указывает дублирование, но возвращает false только тогда, когда оба ключа и содержимое одинаковы, иначе просто добавьте содержимое...
Вы не можете комбинировать, если ID1 и ID2 не совпадают. Если они одинаковы, вы должны проверить, существует ли уже ключ, потому что вы не можете иметь одинаковые ключи в словаре.





Такая быстрая идея, не уверен, что это можно полностью сделать в 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, но на самом деле для вложенной структуры я не мог придумать лучшего плана.
Спасибо, Jlalonde, я столкнулся с некоторыми конфликтами с этим кодом... но в любом случае, спасибо!!
Это работает, если вы хотите сделать это таким образом... Однако вы не указали, как вы хотите обрабатывать конфликты с 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())
});
Отлично @Aotn! Спасибо!!
Вы пробовали Enumerable.Zip docs.microsoft.com/en-us/dotnet/api/…