#python #list #dictionary
#python #Список #словарь
Вопрос:
У меня есть список:
lst = [1, 1, 3, 5, 1, 4, 4]
Ожидаемый результат (ключи — это числа, значения — индекс этих чисел):
{1: [0, 1, 4], 3: [2], 5: [3], 4: [5, 6]}
Ну, я знаю, что есть много способов добиться этого.Нравится:
res = defaultdict(list)
for idx, e in enumerate(lst):
res[e].append(idx)
Или:
res = {}
for idx, e in enumerate(lst):
res.setdefault(e, []).append(idx)
Интересно, сможем ли мы достичь этого с пониманием dict.
Просто для удовольствия :).
Эффективность не важна.(Было бы лучше быть O(n)
).
Комментарии:
1. Вы могли бы, но это было бы неэффективно
2. @DaniMesejo Любые решения приветствуются.
3.
{ i : [j for j, e in enumerate(lst) if e == i] for i in set(lst) }
4. @DaniMesejo Не могли бы вы опубликовать это в качестве ответа? Является ли временная сложность O (n ^ 2)?
5. @KevinMayo Меньшее количество строк не является самоцелью, и его принудительное использование часто приводит к снижению производительности. Не то, чтобы понимание (как показано) имело квадратичную сложность, в то время как варианты на основе циклов, которые у вас есть, являются линейными.
Ответ №1:
Наиболее эффективным, на мой взгляд, является:
from itertools import groupby
from operator import itemgetter
lst = [1, 1, 3, 5, 1, 4, 4]
res = { k : [i for i, _ in group] for k, group in groupby(sorted(enumerate(lst), key=itemgetter(1)), key=itemgetter(1))}
print(res)
Вывод
{1: [0, 1, 4], 3: [2], 4: [5, 6], 5: [3]}
Это O(NlogN)
Комментарии:
1. Импортируйте утилиты
as gb
,as ig
и они будут соответствовать более аккуратно: P2. @schwobaseggl xD
3. Если все перчатки сняты (и я имею в виду действительно сняты), вы можете получить однострочный вариант на основе понимания с линейной сложностью :
res = [(d, d[x].append(i)) for d in [defaultdict(list)] for i, x in enumerate(lst)][0][0]
: D
Ответ №2:
Я добавляю к этому, поскольку @Kevin Mayo заявил, что эффективность не вызывает беспокойства:
lst = [1, 1, 3, 5, 1, 4, 4]
lst_s = {key: [i for i, value in enumerate(lst) if value == key]
for key in set(lst)}
print(lst_s)
# {1: [0, 1, 4], 3: [2], 4: [5, 6], 5: [3]}
ВАРИАЦИЯ С
range(len(lst))
lst = [1, 1, 3, 5, 1, 4, 4]
lst_s = {key: [i for i in range(len(lst)) if lst[i] == key]
for key in set(lst)}
print(lst_s)
# {1: [0, 1, 4], 3: [2], 4: [5, 6], 5: [3]}
Ответ №3:
Вот понимание словаря, которое будет выполняться за O (n) время.
lst = [1, 1, 3, 5, 1, 4, 4]
res = { n:d.setdefault(n,[]).append(i) or d[n] for d in [dict()] for i,n in enumerate(lst) }
print(res)
# {1: [0, 1, 4], 3: [2], 5: [3], 4: [5, 6]}
Итак, ответ — да, это можно сделать в понимании списка. Но я бы не рекомендовал это.