Как можно объединить словари с одинаковыми ключами при переименовании ключей? - PullRequest
1 голос
/ 18 июня 2020

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

d1 = {'1' : 'a1' , '2' : 'a2' , '3' : 'a3'} 
d2 = {'1' : 'b1' , '2' : 'b2' , '3' : 'b3'} 
d3 = {'1' : 'c1' , '2' : 'c2' , '3' : 'c3'}

Вы знаете, как взять эти словари и построить большой словарь, состоящий из всех картинок, но с ключами, начинающимися с 1 и заканчивающимися n, где n - количество картинок? Порядок картинок не имеет значения.

Вот так:

d_new = { ' 1 ' : ' a1 ' , ' 2 ' : ' a2 ' , ' 3 ' : ' a3 ' , ' 4 ' : ' b1 ' , ' 5 ' : ' b2 ' , ' 6 ' : ' b3 ' , ' 7 ' : ' c1 ' , ' 8 ' : ' c2 ' , ' 9 ' : ' c3 ' }

Поскольку ключи одинаковые, я просто получаю словарь длиной в один словарь, когда я их объединяю. Также невозможно изменить имена ключей вручную, а затем объединить словари, потому что количество словарей зависит от пользовательского ввода, от 1 до 104400 созданных словарей.

Я также пробовал вложенные словари, оставив меня с ошибкой "не хешируется" при попытке доступа к изображениям.

Есть ли простое решение моей проблемы, которую я упустил?

Заранее спасибо :).

Ура

РЕДАКТИРОВАТЬ: Спасибо, ребята, большинство ваших решений работали как шарм :)

Ответы [ 6 ]

6 голосов
/ 18 июня 2020

Силой itertools!

С строковыми ключами:

>>> from itertools import chain, count
>>> dicts = [d1, d2, d3]
>>> dict(zip(map(str, count(1)), chain.from_iterable((d.values() for d in dicts))))
{'1': 'a1', '2': 'a2', '3': 'a3', '4': 'b1', '5': 'b2', '6': 'b3', '7': 'c1', '8': 'c2', '9': 'c3'}

С ключами int:

>>> dict(zip(count(1), chain.from_iterable((d.values() for d in dicts))))
{1: 'a1', 2: 'a2', 3: 'a3', 4: 'b1', 5: 'b2', 6: 'b3', 7: 'c1', 8: 'c2', 9: 'c3'}

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

Помните, что вам нужно Python 3.7 или новее для детерминированно упорядоченных словарей.

1 голос
/ 18 июня 2020
from itertools import chain
print({str(k+1):v for (k,v) in enumerate(chain.from_iterable([d.values() for d in [d1,d2,d3] ]))})
{'1': 'a1', '2': 'a2', '3': 'a3', '4': 'b1', '5': 'b2', '6': 'b3', '7': 'c1', '8': 'c2', '9': 'c3'}
1 голос
/ 18 июня 2020

Предполагая, что все мой комментарий имеет место, и вы можете получить свои входные словари в виде списка. Вы упомянули, что у вас было любое количество входных словарей от 1 до 104400 и что они представляют изображения, поэтому я не буду предполагать ничего о ваших входных данных, кроме списка словаря любой длины.

I предположим, что вы уже можете поместить свои пользовательские данные в список, и мы назовем этот список словарей d_list

ie

>>>print(d_list)
>>>[{'1' : 'a1' , '2' : 'a2' , '3' : 'a3'}, {'1' : 'b1' , '2' : 'b2' , '3' : 'b3'}, {'1' : 'c1' , '2' : 'c2' , '3' : 'c3'}]

Итак,

i = 1  # we're starting counting at 1
d_new = {}
for orig_dict in d_list:
    for val in orig_dict.values():
        d_new[str(i)] = val  # str() as originals had string keys
        i += 1

Это должно работать, так как Python 3.6+ словари упорядочены , то есть они запоминают порядок, в котором элементы были добавлены к нему. Таким образом, мы можем более или менее рассматривать dict.values() как список.

Это должно дать точный результат, который вы просили в своем вопросе.

1 голос
/ 18 июня 2020

Используйте itertools.chain() над значениями и enumerate как последовательность для новых ключей:


from itertools import chain


d1 = {'1' : 'a1' , '2' : 'a2' , '3' : 'a3'}
d2 = {'1' : 'b1' , '2' : 'b2' , '3' : 'b3'}
d3 = {'1' : 'c1' , '2' : 'c2' , '3' : 'c3'}


def dict_merge(*dicts):
    return {str(k): v for k, v in enumerate(chain.from_iterable(d.values() for d in dicts), start=1)}


print(dict_merge(d1, d2, d3))

Вывод:

{'1': 'a1', '2': 'a2', '3': 'a3', '4': 'b1', '5': 'b2', '6': 'b3', '7': 'c1', '8': 'c2', '9': 'c3'}
1 голос
/ 18 июня 2020
d1 = {'1' : 'a1' , '2' : 'a2' , '3' : 'a3'}
d2 = {'1' : 'b1' , '2' : 'b2' , '3' : 'b3'}
d3 = {'1' : 'c1' , '2' : 'c2' , '3' : 'c3'}

new_dict = {}
key=1
for old_dict in [d1, d2, d3]:

    for v in old_dict.values():
        new_dict[key] = v
        key += 1
0 голосов
/ 18 июня 2020

Вот как:

d1 = {'1' : 'a1' , '2' : 'a2' , '3' : 'a3'}

d2 = {'1' : 'b1' , '2' : 'b2' , '3' : 'b3'}

d3 = {'1' : 'c1' , '2' : 'c2' , '3' : 'c3'}

l = [d1, d2, d3]

d_new = {}

i = 1

for d in l:
    for k in d.keys():
        d_new[str(i)] = d[k]
        i += 1

print(d_new)

Вывод:

{'1': 'a1', '2': 'a2', '3': 'a3', '4': 'b1', '5': 'b2', '6': 'b3', '7': 'c1', '8': 'c2', '9': 'c3'}

Если строки необходимо заполнить пробелом с обеих сторон:

d1 = {'1' : 'a1' , '2' : 'a2' , '3' : 'a3'}

d2 = {'1' : 'b1' , '2' : 'b2' , '3' : 'b3'}

d3 = {'1' : 'c1' , '2' : 'c2' , '3' : 'c3'}

l = [d1, d2, d3]

d_new = {}

i = 1

for d in l:
    for k in d.keys():
        d_new[f" {i} "] = f" {d[k]} "
        i += 1

print(d_new)

Вывод:

{' 1 ': ' a1 ', ' 2 ': ' a2 ', ' 3 ': ' a3 ', ' 4 ': ' b1 ', ' 5 ': ' b2 ', ' 6 ': ' b3 ', ' 7 ': ' c1 ', ' 8 ': ' c2 ', ' 9 ': ' c3 '}
...