pythonic способ связать элементы списка с их индексами - PullRequest
9 голосов
/ 14 мая 2010

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

Я могу сделать это так:

>>> t = (5,6,7)
>>> d = dict(zip(t, range(len(t))))
>>> d
{5: 0, 6: 1, 7: 2}

это неплохо, но я ищу что-то более элегантное.

Я сталкивался со следующим, но это противоположно тому, что мне нужно:

>>> d = dict(enumerate(t))
>>> d
{0: 5, 1: 6, 2: 7}

Пожалуйста, поделитесь своими решениями,
Спасибо

РЕДАКТИРОВАТЬ : Python 2.6.4

Для списков, содержащих 1000 элементов, версия dict (zip) является самой быстрой, генератор и версии понимания списков практически идентичны, они примерно в 1,5 раза медленнее, а функциональная карта (обращенная) значительно медленнее.

$ python -mtimeit -s "t = range (int (1e3))" "d = dict (zip (t, range (len (t)))))"
1000 петель, лучшее из 3: 277 юсек на петлю

$ python -mtimeit -s "t = range (int (1e3))" "d = dict ([(y, x) для x, y в перечислении (t)])"
1000 петель, лучшее из 3: 426 мксек на петлю

$ python -mtimeit -s "t = range (int (1e3))" "d = dict ((y, x) для x, y в перечислении (t))"
1000 петель, лучшее из 3: 437 усек за петлю

$ python -mtimeit -s "t = range (int (1e3))" "d = dict (map (инвертировано, перечислить (t)))"
100 циклов, лучшее из 3: 3,66 мсек на цикл

Я попытался запустить одни и те же тесты для более длинных и более коротких списков (1e2, 1e4, 1e5), и время цикла увеличивается линейно с длиной списка.

Может ли кто-нибудь рассчитать версию py 2.7+?

Ответы [ 6 ]

14 голосов
/ 14 мая 2010

Вы можете использовать понимание списка (или генератор, в зависимости от вашей версии Python), чтобы выполнить простой обмен на месте для второго примера.


Использование списка понимания:

d = dict([(y,x) for x,y in enumerate(t)])

Использование выражения генератора (Python 2.4 и выше):

d = dict((y,x) for x,y in enumerate(t))
13 голосов
/ 14 мая 2010

В Python2.7 + вы можете написать это так

>>> t = (5,6,7)
>>> d = {x:i for i,x in enumerate(t)}
>>> print d
{5: 0, 6: 1, 7: 2}
4 голосов
/ 14 мая 2010
>>> dict((x,i) for i,x in enumerate(t))
{5: 0, 6: 1, 7: 2}
>>>
2 голосов
/ 14 мая 2010

Как уже все писали, в Python 2.6 я бы посчитал следующее наиболее питоническим:

>>> dict((x, i) for i, x in enumerate(t))
{5: 0, 6: 1, 7: 2}

Тем не менее, в момент функционального безумия я бы написал:

>>> dict(map(reversed, enumerate(t)))
{5: 0, 6: 1, 7: 2}
2 голосов
/ 14 мая 2010

Являются ли все ваши элементы уникальными (т. Е. Ваш список никогда не будет 5,6,7,7)? Решение dict будет работать, только если все ваши элементы уникальны.

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

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

Почему вы пытаетесь сохранить значение индекса, когда вы можете просто получить индекс из списка?

0 голосов
/ 14 мая 2010

Мне нравится dict (zip (t, range (len (t))))).

...