Понимание списка - попытка создать словарь из массива пар «ключ-значение» - PullRequest
0 голосов
/ 14 января 2020

При попытке создать dict с использованием понимания списка (без перезаписи сгенерированных ключей списка)

x = {}
entries = [[1,'1a'], [2,'2a'], [3,'3a'], ['1', '1b'], ['2', '2b'], ['3', '3b']]
discardable = [x.setdefault(entry[0], []).append(entry[1]) for entry in entries]

Error: name 'x' is not defined

Я ожидал, что x будет заполнен как:

{1: ['1a', '1b'], 2: ['2a', '2b'], 3: ['3a', '3b']}

Как это объяснить / сделать эту работу? Есть ли другой способ добиться этого?

Ответы [ 5 ]

0 голосов
/ 14 января 2020

Как это объяснить / заставить это работать?

Понимание создает один выход для каждого входа, и они не предназначены для мутации

Есть ли другой способ добиться этого?

Используйте нормальную процедурную l oop. Или используйте мультидикт, но стандартная библиотека его не предоставляет.

Вы можете выполнять функциональные преобразования, пока не получите правильную «форму» (используя sorted, itertools.groupby и еще несколько отображений), но я не не думаю, что это того стоит, стандарт болота for l oop был бы гораздо более читабельным:

for k, v in entries:
    x.setdefault(int(x), []).append(v)

против:

x = {
    x: list(v[1] for v in vs)
    for x, vs in itertools.groupby(
        sorted((int(k), v) for k, v in entries),
        lambda it: it[0]
    )
}

понимание менее читаемый и менее эффективный

0 голосов
/ 14 января 2020

Вы можете использовать понимание слова . они работают так же, как списки

entries = [[1,'1a'], [2,'2a'], [3,'3a'], ['1', '1b'], ['2', '2b'], ['3', '3b']]

# Build a dictionary from the values in entries
discardable = {key:val for key, val in entries}

print (discardable)
# Result: {1: '1a', 2: '2a', 3: '3a', '1': '1b', '2': '2b', '3': '3b'}
0 голосов
/ 14 января 2020

Некоторые из ключей str, а некоторые int, так что это даст

{'1': ['1a', '1b'], 2: ['2a'], 3: ['3a'], '2': ['2b'], '3': ['3b']}

Вам нужно разыграть entry[0] до int

x = {}
entries = [[1,'1a'], [2,'2a'], [3,'3a'], ['1', '1b'], ['2', '2b'], ['3', '3b']]
[x.setdefault(int(entry[0]), []).append(entry[1]) for entry in entries]

print(x) даст

{1: ['1a', '1b'], 2: ['2a', '2b'], 3: ['3a', '3b']}
0 голосов
/ 14 января 2020

То, что вы хотите, это объединить значения (1, '1'), (2, '2'), (3, '3'). Предоставленный вами код работает, но он не обрабатывает тип от int до str. Все, что вам нужно сделать, это привести str в int, чтобы значение было объединено.

Попробуйте это:

x = {}
entries = [[1,'1a'], [2,'2a'], [3,'3a'], ['1', '1b'], ['2', '2b'], ['3', '3b']]
discardable = [x.setdefault(int(entry[0]), []).append(entry[1]) for entry in entries]
0 голосов
/ 14 января 2020

Вы можете попробовать:

from collections import defaultdict
entries = [['1','1a'], [2,'2a'], [3,'3a'], ['1', '1b'], ['2', '2b'], ['3', '3b']]
x = defaultdict(list)
[x[a].append(b) for a,b in entries]
x = dict(x)

Выход

{'1': ['1a', '1b'], 2: ['2a'], 3: ['3a'], '2': ['2b'], '3': ['3b']}
...