2010-05-14 12 views
8

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

я могу сделать это таким образом:

>>> 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} 

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

EDIT: Python 2.6.4

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

$ питон -mtimeit -s "т = диапазон (интермедиат (1e3))" "d = ДИКТ (застежка-молния (т, диапазон (Len (т))))"
1000 петель, лучше всего из 3: 277 мксек на петле

$ питона -mtimeit -s "т = диапазон (интермедиат (1e3))" "d = ДИКТ ([(у, х) при х, у в Перечислим (т)])"
1000 петли, наилучшее из 3: 426 usec за цикл

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

$ питона -mtimeit -s "т = диапазон (интермедиат (1e3))" "d = ДИКТ (отображение (обратное, перечислить (т)))"
100 петель, лучше всего 3: 3,66 мс в петле

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

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

+0

Мне любопытно - какая из реализаций выполняется быстрее? Кстати, Chewy, какую версию Python вы используете? –

ответ

13

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


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

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

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

d = dict((y,x) for x,y in enumerate(t)) 
+2

Вам не нужен '[]' там. 'dict' отлично работает с выражением генератора (сохраняет промежуточный список) –

+1

Да, поэтому я написал« в зависимости от вашей версии python ». Генераторы были вокруг долгое время (начиная с 2.4), поэтому я буду включать в себя как – kibibu

+1

Где используется Python <2.4? – jfs

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

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

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

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

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

+0

все элементы списка уникальны. Я сохраняю индекс для быстрого поиска в другой структуре данных. –

+0

Это звучит как бесполезный уровень косвенности, если все элементы уникальны, проверяйте членство с 'in' и index с' index() '. Я предполагаю, что вы представляете, что словарь с поддержкой хеш-карт поможет вам быстрее искать, чем 'index()' будет. В Python преждевременная оптимизация действительно зла, потому что ваши интуиции о «быстрее» часто ошибочны до фактического времени. Заставьте это работать, затем узнайте, где вы медленны, добавленная сложность не стоит. – msw

+0

@ Dragan, вы изменяете свой список или статичны? –

0

Мне нравится dict (zip (t, range (len (t)))) лучший.

+0

Почему? Это быстрее? –

+0

Это коротко, просто и точно. – Arafangion

12

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

>>> t = (5,6,7) 
>>> d = {x:i for i,x in enumerate(t)} 
>>> print d 
{5: 0, 6: 1, 7: 2} 
+0

+1 для демонстрации красоты понимания Py3k. – Dustin

2

Как все уже написано в 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}