Есть ли лучший способ преобразовать список в словарь в Python с ключами, но без значений? - PullRequest
6 голосов
/ 20 июня 2009

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

Единственный способ, которым я мог найти это, был против.

«Использование списочных представлений, когда результат игнорируется, вводит в заблуждение и неэффективно. for цикл лучше»

myList = ['a','b','c','d']
myDict = {}
x=[myDict.update({item:None}) for item in myList]

>>> myDict
{'a': None, 'c': None, 'b': None, 'd': None}

Это работает, но есть ли лучший способ сделать это?

Ответы [ 6 ]

23 голосов
/ 20 июня 2009

Использование dict.fromkeys:

>>> my_list = [1, 2, 3]
>>> dict.fromkeys(my_list)
{1: None, 2: None, 3: None}

Значения по умолчанию None, но вы можете указать их в качестве необязательного аргумента:

>>> my_list = [1, 2, 3]
>>> dict.fromkeys(my_list, 0)
{1: 0, 2: 0, 3: 0}

Из документов:

a.fromkeys (seq [, value]) Создает новый словарь с ключами от seq и значения установлены в значение.

dict.fromkeys - это метод класса, который возвращает новый словарь. значение по умолчанию Нет. Новое в версии 2.3.

15 голосов
/ 20 июня 2009

Вы можете использовать set вместо dict:

>>> myList=['a','b','c','d']
>>> set(myList)
set(['a', 'c', 'b', 'd'])

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

5 голосов
/ 20 июня 2009

Отвечая на вопрос о производительности исходного опрашивающего (для поисков в dict против set), несколько удивительно, что dict поисков может быть чуть-чуть быстрее (в Python 2.5.1 на моем довольно медленномнапример, при условии, что половина поисков не удалась, а половина удалась.Вот как можно выяснить:

$ python -mtimeit -s'k=dict.fromkeys(range(99))' '5 in k and 112 in k'
1000000 loops, best of 3: 0.236 usec per loop
$ python -mtimeit -s'k=set(range(99))' '5 in k and 112 in k'
1000000 loops, best of 3: 0.265 usec per loop

делает каждую проверку несколько раз, чтобы убедиться, что она повторяется.Таким образом, если эти 30 наносекунд или меньше на медленном ноутбуке находятся в абсолютно критическом узком месте, возможно, стоит пойти на неясное dict.fromkeys решение, а не на простое, очевидное, читаемое и четко правильное set (необычно -почти всегда в Python простое и прямое решение также имеет преимущества в производительности).

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

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

1 голос
/ 20 июня 2009

Может быть, вы можете использовать itertools:

>>>import itertools
>>>my_list = ['a','b','c','d']
>>>d = {}
>>>for x in itertools.imap(d.setdefault, my_list): pass
>>>print d
{'a': None, 'c': None, 'b': None, 'd': None}

Для огромных списков, возможно, это очень хорошо: P

1 голос
/ 20 июня 2009

Вы можете использовать понимание списка:

my_list = ['a','b','c','d']
my_dict = dict([(ele, None) for ele in my_list])
1 голос
/ 20 июня 2009

А вот довольно неправильный и неэффективный способ сделать это с помощью карты:

>>> d = dict()
>>> map (lambda x: d.__setitem__(x, None), [1,2,3])
[None, None, None]
>>> d
{1: None, 2: None, 3: None}
...