python преобразовать список в словарь [дубликат]
этот вопрос уже есть ответ здесь:
- преобразование списка в словарь на Python 13 ответов
l = ["a", "b", "c", "d", "e"]
Я хочу преобразовать этот список в словарь, например:
d = {"a": "b", "c": "d", "e": ""}
таким образом, в основном, эвены будут ключами, тогда как шансы будут значениями. Я знаю, что я могу сделать это в "не-подходящие для Python" способ такой как цикл for с утверждениями if, но я считаю, что для этого должен быть более "питонический" способ. Так что, я ценю любую помощь:)
4 ответа:
через обычный рецепт окунь, вы могли бы сделать:
Python 2:
d = dict(itertools.izip_longest(*[iter(l)] * 2, fillvalue=""))Python 3:
d = dict(itertools.zip_longest(*[iter(l)] * 2, fillvalue=""))
если вы все еще думаете, что! Вы не будете одиноки, на самом деле это не так сложно, позвольте мне объяснить.
как превратить список в словарь, используя только встроенные функции
мы хотим превратить следующий список в словарь, используя нечетные записи (считая от 1) в качестве ключей, сопоставленных с их последовательными четными записями.
l = ["a", "b", "c", "d", "e"]dict ()
для создания словаря мы можем использовать встроенный который в основном использует ряд или короткий фрагмент нотация, но это то, что долго кусочек нотация выглядит как и то, что мы можем сделать с шаг:
>>> 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 выглядит как a, теперь они являются двумя отдельными объектами, и именно поэтому мы предпочитаем использовать рецепт окунь вместо.
групер рецепт
хотя grouper объясняется как часть модуля 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 намного превосходит функцию map на больших объемах, как показывает бенчмарк против 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!