2010-05-14 12 views
8

Mam listę wartości i chcę umieścić je w słowniku, który odwzorowałby każdą wartość na jej indeks.Pythonowy sposób powiązania elementów listy z ich indeksami

mogę zrobić to w ten sposób:

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

to nie jest zły, ale szukam czegoś bardziej eleganckiego.

Natknąłem Poniżej, ale robi przeciwieństwo tego, czego potrzebuję:

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

Proszę podzielić się rozwiązania,
Dziękuję

EDIT: Python 2.6.4

W przypadku list zawierających 1000 elementów wersja dykt (zip) jest najszybsza, wersje generatora i wersji zrozumiałej są praktycznie identyczne i mają wartość ~ 1,5 razy wolniej, a mapa funkcjonalna (odwrócona) jest znacznie wolniejsza.

$ pyton -mtimeit -s "t = Range (int (1e3))", "d = DICT (ZIP (t, zakres (len (t))))"
1000 pętle, najlepiej 3: 277 mikrosekund każdej pętli

$ pyton -mtimeit -s "t = Range (int (1e3))", "d = DICT ([(r x) dla x, Y, w enumerate (t)])"
1000 pętle, najlepiej z 3: 426 użycia w pętli

$ python -mtimeit -s "t = zakres (int (1e3))" "d = dict ((y, x) dla x, y w wyliczeniu (t)) "
1000 pętli, najlepiej od 3: 437 przy użyciu pętli

$ python -mtimeit -s "t = zakres (int (1e3))" "d = dict (map (odwrócone, wyliczone (t)))"
100 pętli, najlepiej 3: 3,66 ms na pętlę

Próbowałem uruchomić te same testy dla dłuższych i krótszych list (1e2, 1e4, 1e5), a czas na pętlę skaluje się liniowo wraz z długością listy.

Czy ktoś może skorzystać z wersji py 2.7+?

+0

Jestem ciekawy - które z wdrożeń jest szybsze? Przy okazji, Chewy, której wersji Pythona używasz? –

Odpowiedz

13

Możesz użyć zrozumienia list (lub generatora, w zależności od wersji pythona), aby wykonać prostą zamianę w miejscu dla twojego drugiego przykładu.


Korzystanie z listy ze zrozumieniem:

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

Korzystanie wyrażenie generatora (Python 2.4 i wyżej):

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

Nie potrzebujesz "[]" tam. 'dict' działa dobrze z wyrażeniem generatora (zapisuje tworzenie pośredniej listy) –

+1

Tak, dlatego napisałem" w zależności od wersji pythona ". Generatory były jednak od dłuższego czasu (od wersji 2.4), więc będę zawierał zarówno – kibibu

+1

Gdzie używany jest Python <2.4? – jfs

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

są wszystkie twoje elementy unikatowe (tj twoja lista nigdy nie będzie 5,6,7,7)? Rozwiązanie Dict działa tylko wtedy, gdy wszystkie twoje elementy są unikalne.

Zapisując indeks, zasadniczo powielamy informacje, ponieważ można po prostu zapytać o bieżący indeks pozycji na liście. Powielanie informacji zwykle nie jest najlepszym pomysłem, ponieważ pozwala na uniknięcie synchronizacji jednego zestawu danych z drugim.

Jeśli lista jest modyfikowana, nic nie stoi na przeszkodzie, aby przypadkowo przypisać ten sam indeks do więcej niż jednego przedmiotu.

Dlaczego próbujesz zapisać wartość indeksu, skoro możesz po prostu pobrać indeks z listy?

+0

wszystkie elementy listy są unikalne. Przechowuję indeks dla szybkiego wyszukiwania w innej strukturze danych. –

+0

Brzmi to jak bezużyteczny poziom pośrednictwa, jeśli wszystkie elementy są unikatowe, testuj przynależność do 'in' i indeksuj za pomocą' index() '. Zgaduję, że wyobrażasz sobie, że słownik ze skrótem hash-map da ci szybsze wyszukiwanie niż 'index()'. W Pythonie przedwczesna optymalizacja jest naprawdę zła, ponieważ twoje intuicje dotyczące "szybszego" często są błędne do czasu rzeczywistego. Spraw, aby działało, a następnie sprawdź, gdzie jesteś wolny, a dodatkowa złożoność nie jest tego warta. – msw

+0

@Dragan, modyfikujesz listę lub czy pozostanie ona statyczna? –

0

Lubię dyktować (najlepiej zip (t, range (len (t)))).

+0

Dlaczego? Czy to jest szybsze? –

+0

Jest krótki, prosty i do rzeczy. – Arafangion

12

W Python2.7 + można napisać to tak

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

+1 za pokazanie piękna pojęć dyktowanych przez Py3k. – Dustin

2

Jak wszyscy już napisane w Pythonie 2.6 Chciałbym rozważyć następujące kwestie jak najbardziej pythonic:

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

Nadal w momencie szału funkcjonalnego napisałbym:

>>> dict(map(reversed, enumerate(t))) 
{5: 0, 6: 1, 7: 2} 
Powiązane problemy