Python конвертировать список в словарь

l = ["a", "b", "c", "d", "e"]

Я хочу преобразовать этот список в словарь, например:

d = {"a": "b", "c": "d", "e": ""}

Итак, в основном, evens будут ключами, тогда как коэффициенты будут значениями. Я знаю, что могу сделать это с помощью "непифонного" способа, такого как цикл for с операторами if, но я считаю, что для этого должен быть более "питонический" способ. Итак, я ценю любую помощь:)

Ответ 1

Используя обычный рецепт grouper recipe, вы можете сделать:

Python 2:

d = dict(itertools.izip_longest(*[iter(l)] * 2, fillvalue=""))

Python 3:

d = dict(itertools.zip_longest(*[iter(l)] * 2, fillvalue=""))

Ответ 2

Если вы все еще думаете, что! Вы не были бы одиноки, на самом деле это не так сложно, позвольте мне объяснить.

Как превратить список в словарь, используя только встроенные функции

Мы хотим превратить следующий список в словарь с использованием нечетных записей (считая от 1) в качестве ключей, сопоставленных с их последовательными четными записями.

l = ["a", "b", "c", "d", "e"]

ДИКТ()

Чтобы создать словарь, мы можем использовать встроенную функцию dict для Типы сопоставления в соответствии с руководством, поддерживая следующие методы.

dict(one=1, two=2)
dict({'one': 1, 'two': 2})
dict(zip(('one', 'two'), (1, 2)))
dict([['two', 2], ['one', 1]])

Последний вариант предполагает, что мы поставляем список списков с 2 значениями или (key, value) кортежей, поэтому мы хотим превратить наш последовательный список в:

l = [["a", "b"], ["c", "d"], ["e",]]

Мы также вводим функцию zip, одну из встроенных функций, которая в руководстве объясняется:

возвращает список кортежей, где i-й кортеж содержит i-й элемент из каждого из аргументов

Другими словами, если мы можем превратить наш список в два списка a, c, e и b, d, то zip сделает все остальное.

нотация среза

Slicings, который мы видим с Strings, а также далее в Список разделов, который в основном использует диапазон или короткий фрагмент, но это то, что длинный фрагмент выглядит так, и мы можем выполнить шаг:

>>> l[::2]
['a', 'c', 'e']

>>> l[1::2]
['b', 'd']

>>> zip(['a', 'c', 'e'], ['b', 'd'])
[('a', 'b'), ('c', 'd')]

>>> dict(zip(l[::2], l[1::2]))
{'a': 'b', 'c': 'd'}

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

>>> a = [1, 2, 3]
>>> b = a
>>> b
[1, 2, 3]

>>> b is a
True

>>> b = a[:]
>>> b
[1, 2, 3]

>>> b is a
False

Несмотря на то, что b выглядит как два отдельных объекта, и поэтому мы предпочитаем использовать рецепт группы > .

рецепт группы

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

Какой-то серьезный вуду? =) Но на самом деле это не что иное, как немного синтаксического сахара для специй, рецепт группокера выполняется следующим выражением.

*[iter(l)]*2

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

zip для кратчайшего

>>> l*2
['a', 'b', 'c', 'd', 'e', 'a', 'b', 'c', 'd', 'e']

>>> [l]*2
[['a', 'b', 'c', 'd', 'e'], ['a', 'b', 'c', 'd', 'e']]

>>> [iter(l)]*2
[<listiterator object at 0x100486450>, <listiterator object at 0x100486450>]

>>> zip([iter(l)]*2)
[(<listiterator object at 0x1004865d0>,),(<listiterator object at 0x1004865d0>,)]

>>> zip(*[iter(l)]*2)
[('a', 'b'), ('c', 'd')]

>>> dict(zip(*[iter(l)]*2))
{'a': 'b', 'c': 'd'}

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

Вы выполнили бы очень то же самое со следующим, которое может содержать меньший Что такое?.

>>> it = iter(l)     
>>> dict(zip(it, it))
{'a': 'b', 'c': 'd'}

Как насчет пустого ключа e, если вы заметили, что он отсутствует во всех примерах, потому что zip выбирает самый короткий из двух аргументов, так что нам делать.

Ну, одно решение может добавлять пустые значения в списки нечетной длины, вы можете использовать append и инструкцию if, которая могла бы сделать трюк, хотя и немного скучный, правильно?

>>> if len(l) % 2:
...     l.append("")

>>> l
['a', 'b', 'c', 'd', 'e', '']

>>> dict(zip(*[iter(l)]*2))
{'a': 'b', 'c': 'd', 'e': ''}

Теперь, прежде чем вы отмахнетесь, чтобы пойти типа from itertools import izip_longest, вы можете быть удивлены, узнав, что это не требуется, мы можем добиться того же, даже лучшего ИМХО, только с встроенными функциями.

карта для самого длинного

Я предпочитаю использовать функцию map() вместо izip_longest(), которая не только использует короткие синтаксис не требует импорта, но при необходимости автоматически может присваивать фактическое None пустое значение.

>>> l = ["a", "b", "c", "d", "e"]
>>> l
['a', 'b', 'c', 'd', 'e']

>>> dict(map(None, *[iter(l)]*2))
{'a': 'b', 'c': 'd', 'e': None} 

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

$ time python -c 'dict(map(None, *[iter(range(10000000))]*2))'
real    0m3.755s
user    0m2.815s
sys     0m0.869s
$ time python -c 'from itertools import izip_longest; dict(izip_longest(*[iter(range(10000000))]*2, fillvalue=None))'
real    0m2.102s
user    0m1.451s
sys     0m0.539s

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

$ time python -c 'dict(map(None, *[iter(range(100))]*2))'
real    0m0.046s
user    0m0.029s
sys     0m0.015s
$ time python -c 'from itertools import izip_longest; dict(izip_longest(*[iter(range(100))]*2, fillvalue=None))'
real    0m0.067s
user    0m0.042s
sys     0m0.021s

$ time python -c 'dict(map(None, *[iter(range(100000))]*2))'
real    0m0.074s
user    0m0.050s
sys     0m0.022s
$ time python -c 'from itertools import izip_longest; dict(izip_longest(*[iter(range(100000))]*2, fillvalue=None))'
real    0m0.075s
user    0m0.047s
sys     0m0.024s

Ничего не трогай! =)

NJoy!

Ответ 3

Я бы пошел на рекурсии:

l = ['a', 'b', 'c', 'd', 'e', ' ']
d = dict([(k, v) for k,v in zip (l[::2], l[1::2])])

Ответ 4

Не уверен, поможет ли это вам или нет, но он работает со мной:

l = ["a", "b", "c", "d", "e"]
outRes = dict((l[i], l[i+1]) if i+1 < len(l) else (l[i], '') for i in xrange(len(l)))