У меня есть список на Python, который я хотел бы преобразовать в словарь. Список такой:

l = [('1:', [362.5815, 162.5823]), ('2:', [154.1328, 354.133]), ('3:', [168.9325, 368.9331]), ('4:', [9.9201, 209.9206]), ('5:', [106.4842, 306.4844])]

В dict должны быть целые числа 1,2,3,4,5 в качестве ключей и списки в качестве значений. Я пробовал использовать

def Convert(l):
    it = iter(l)
    res_dct = dict(zip(it, it))
    return res_dct  

А также

def Convert(l):
    res_dct = {l[i]: l[i + 1] for i in range(0, len(l), 2)}
    return res_dct

Но они не работают из-за того, что список - это нехешируемый тип. Как еще я мог преобразовать этот список? заранее спасибо

-1
LucasTU 23 Ноя 2021 в 18:10
Ваш второй пример почти прав. Но вам не нужен ключ l[i], потому что это кортеж. Вместо этого вам нужен l[i][0], первый элемент кортежа, в качестве ключа.
 – 
Code-Apprentice
23 Ноя 2021 в 18:18
@ Code-Apprentice - я так не думаю. Даже если плакат выполняет l[i][0], это строка с двоеточием, а не целое число, и он пропускает все остальные элементы списка.
 – 
tdelaney
23 Ноя 2021 в 18:22
Да, изменение l[i] на l[i][0] и l[i + 1] на l[i][1] - это только первый шаг к решению. Это изменение решит немедленную ошибку, заключающуюся в том, что список не может быть хеширован. Я считаю, что OP движется в правильном направлении, чтобы попасть туда.
 – 
Code-Apprentice
23 Ноя 2021 в 18:29
@ Code-Apprentice - Но это неправильное направление. Не следует использовать диапазон + индексирование, когда простая итерация выполнит свою работу. Первый пример ближе к правому, чем второй.
 – 
tdelaney
23 Ноя 2021 в 18:34
Тот факт, что range() не питонический, не означает, что его использование вообще не работает.
 – 
Code-Apprentice
23 Ноя 2021 в 18:38

3 ответа

Лучший ответ
def Convert(l):
    res_dct = {l[i]: l[i + 1] for i in range(0, len(l), 2)}
    return res_dct

Это почти правильно. Проблема в том, что l[i] - это целый кортеж в качестве ключа. Вместо этого вам нужен первый элемент этого кортежа: l[i][0]. Точно так же значение должно быть l[i][1], чтобы получить второй элемент каждого кортежа. Имея это в виду, нет причин пропускать все остальные элементы в списке. Собираем все вместе:

def Convert(l):
    res_dct = {l[i][0]: l[i][1] for i in range(len(l))}
    return res_dct

Более питонический способ - перебирать элементы списка напрямую, а не использовать индексы в списке:

def Convert(l):
    res_dct = {i[0]: i[1] for i in l}
    return res_dct

И вы можете использовать еще синтаксис Python, чтобы избавиться от индексации кортежа:

def Convert(l):
    res_dct = {k: v for k, v in l}
    return res_dct

Но класс dict() уже делает это со списком пар, поэтому мы можем упростить его еще больше:

def Convert(l):
    res_dct = dict(l)
    return res_dct

Все эти три варианта превратят список кортежей в словарь. Однако они будут использовать элементы именно такими, какие они есть. В частности, ключом будет строка с цифрами, а затем двоеточие. Если вы хотите изменить их ключи на целые числа, вы не можете использовать окончательную версию, которая вызывает dict(). Вместо этого мы воспользуемся пониманием словаря и применим к ключу некоторые функции:

def Convert(l):
    res_dct = {int(k.strip(':')): v for k, v in l}
    return res_dct

После всего этого я бы подумал о том, чтобы просто составить список списков. Когда ключи расположены в последовательном порядке, список имеет больше смысла, чем словарь:

def Convert(l):
    res = [v for k, v in l]
    return res

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

0
Code-Apprentice 23 Ноя 2021 в 18:41
1
Большое спасибо за объяснение. Версия, возвращающая ключи в виде целых чисел, идеальна!
 – 
LucasTU
23 Ноя 2021 в 18:40
d = dict()   
for (k, v) in l:
    d[k.strip(':')] = v

Помните о повторяющихся ключах в вашем списке, так как будет сохранен только последний список, если вы ожидаете дублирования ключей, вам нужно выбрать стратегию для их обработки по-другому (например, объединить их или сохранить первое назначение вместо последнего присвоения, как реализовано. здесь)

ИЗМЕНИТЬ В приведенном ниже комментарии к пониманию dict и преобразованию int для ключей это также можно сделать (хотя не так уверен в разборчивости)

{int(key.strip(':')):value for (key,value) in l}
2
Jonathan 23 Ноя 2021 в 18:20
И я думаю, вам нужно добавить int(..) в тете, иначе это будут просто строки.
 – 
tdelaney
23 Ноя 2021 в 18:15
Вы можете сократить это до одной строки с пониманием слов.
 – 
Code-Apprentice
23 Ноя 2021 в 18:16
Хороший ответ, но вы можете добавить альтернативный d = {int(v[0].strip(":")):v[1] for v in l} в качестве понимания словаря, что, я думаю, будет типичным решением для Python.
 – 
tdelaney
23 Ноя 2021 в 18:18

Вы можете использовать понимание словаря и перечислять

{i: v[1] for i,v in enumerate(l, 1)}
-1
Sayse 23 Ноя 2021 в 18:17
Предполагается, что целые числа всегда равны 1, 2, 3, ... Не удалось бы, если бы данные были чем-то другим, кроме этого. Я думаю, вы здесь слишком многого предполагали.
 – 
tdelaney
23 Ноя 2021 в 18:19
- Возможно, но оператор также говорит: «В dict должны быть целые числа 1,2,3,4,5 в качестве ключей, а списки - в качестве значений», поэтому текущие первые элементы кортежей могут так же легко вводить в заблуждение
 – 
Sayse
23 Ноя 2021 в 18:22
2
Но это только потому, что в примере было «1:» и т. Д. Мы не знаем, является ли это правилом или только одним примером. Это скорее вопрос к OP, чем ответ, пока мы не узнаем.
 – 
tdelaney
23 Ноя 2021 в 18:25
Использование enumerate() предполагает, что список ввода уже находится в правильном порядке. Вместо этого для получения ключа безопаснее использовать первый элемент каждого кортежа.
 – 
Code-Apprentice
23 Ноя 2021 в 18:32
@ Code-Apprentice - я бы согласился, если это было намерением OP, я интерпретировал немного иначе, например, исходный список ops был отсортирован, и они потенциально преобразовывали его в словарь «рангов», то есть 1-й, 2-й, 3-й, в отличие от значение, используемое для сортировки (на основе "должно быть целое число 1,2,3,4,5")
 – 
Sayse
23 Ноя 2021 в 18:39