2009-05-27 2 views
1

Ich habe nach einem Rezept/Beispiel gesucht, um eine Liste von Tupeln zu indizieren, ohne eine Modifikation des Dekors, Sortierens, undekorierten Ansatzes vorzunehmen.Gibt es in Python eine Möglichkeit, eine Liste von Containern (Tupel, Listen, Wörterbücher) nach einem Element eines Containers zu indizieren?

Zum Beispiel:

l=[(a,b,c),(x,c,b),(z,c,b),(z,c,d),(a,d,d),(x,d,c) . . .] 

Der Ansatz, den ich verwendet haben ist ein Wörterbuch mit defaultdict des zweiten Elements zu bauen

from collections import defaultdict 

tdict=defaultdict(int) 

for myTuple in l: 
    tdict[myTuple[1]]+=1 

Dann muss ich die zweite nur aus einer Liste erstellen Element im Tupel für jeden Eintrag in der Liste. Zwar gibt es eine Reihe von Möglichkeiten, um dort einen einfachen Ansatz sind ist:

tempList=[myTuple[1] for myTuple in l] 

und dann einen Index jedes Elements in TDICT

indexDict=defaultdict(dict) 
for key in tdict: 
    indexDict[key]['index']=tempList.index(key) 

Offensichtlich erzeugen bedeutet dies nicht sehr Pythonic scheinen. Ich habe versucht, Beispiele oder Einsichten zu finden, die denken, dass ich in der Lage sein sollte, etwas Magisches zu verwenden, um den Index direkt zu bekommen. Bisher kein Glück.

Hinweis, ich verstehe, dass ich meinen Ansatz ein wenig direkter und nicht generieren kann.

Ausgang könnte ein Wörterbuch mit dem Index

indexDict={'b':{'index':0},'c':{'index':1},'d':{'index':4},. . .} 

sein Nach viel von Nadia Antworten Lernen Ich denke, die Antwort ist nein.

Während ihre Antwort funktioniert, denke ich, dass es komplizierter ist als nötig. Ich würde einfach

def build_index(someList): 
    indexDict={} 
    for item in enumerate(someList): 
     if item[1][1] not in indexDict: 
      indexDict[item[1][1]]=item[0] 
    return indexDict 
+1

Ich bin verwirrt, was Sie versuchen zu tun. Was ist Ihre gewünschte Ausgabe? Dein Code funktioniert nicht ganz - was soll in der Zeile "tdict [myTuple [1]] + = count" stehen? –

+0

Können Sie ein Beispiel für die erwartete Ausgabe oder Struktur angeben? –

+0

Entschuldigung - jedes Mal, wenn ich ein Wörterbuch erstelle, um die Anzahl eines Elements zu erhalten, schreibe ich immer + = count, bevor ich es auf + = 1 korrigiere. Ich habe eine Gehirnzelle. – PyNEwbie

Antwort

5

Dies wird das Ergebnis generieren Sie

dict((myTuple[1], index) for index, myTuple in enumerate(l)) 

>>> l = [(1, 2, 3), (4, 5, 6), (1, 4, 6)] 
>>> dict((myTuple[1], index) for index, myTuple in enumerate(l)) 
{2: 0, 4: 2, 5: 1} 

Und wenn Sie sich mit einem Wörterbuch bestehen, den Index zu repräsentieren:

dict((myTuple[1], {'index': index}) for index, myTuple in enumerate(l)) 

Das Ergebnis wird:

{2: {'index': 0}, 4: {'index': 2}, 5: {'index': 1}} 

EDIT Wenn Sie Schlüsselkollision zu handhaben wollen, dann werden Sie die Lösung wie diese erweitern müssen:

def build_index(l): 
    indexes = [(myTuple[1], index) for index, myTuple in enumerate(l)] 
    d = {} 
    for e, index in indexes: 
     d[e] = min(index, d.get(e, index)) 
    return d 

>>> l = [(1, 2, 3), (4, 5, 6), (1, 4, 6), (2, 4, 6)] 
>>> build_index(l) 
{2: 0, 4: 2, 5: 1} 

EDIT 2

Und eine verallgemeinerte und kompakt Lösung (in einer ähnlichen Definition sorted)

def index(l, key): 
    d = {} 
    for index, myTuple in enumerate(l): 
     d[key(myTuple)] = min(index, d.get(key(myTuple), index)) 
    return d 

>>> index(l, lambda a: a[1]) 
{2: 0, 4: 2, 5: 1} 

Die Antwort auf Ihre Frage lautet also: In Python gibt es eine Möglichkeit, eine Liste von Containern (Tupel, Listen, Wörterbücher) durch ein Element eines Containers ohne Vorverarbeitung zu indizieren. Aber Ihre Anfrage, das Ergebnis in einem Wörterbuch zu speichern, macht es unmöglich, ein Einliner zu sein. Aber hier gibt es keine Vorverarbeitung. Die Liste wird nur einmal durchlaufen.

+0

Das ist glatt. Ich sehe, es ist eine Frage des richtigen Denkens über das Problem. Ich sehe, dass dies auf jeden Subcontainer in einer Liste von Containern verallgemeinert werden sollte. Cool und danke – PyNEwbie

+0

Eigentlich Nadia das ist nah aber nicht ganz da. Versuchen Sie, ein weiteres Tupel mit einem gemeinsamen mittleren Wert hinzuzufügen, sagen Sie add (2,4,6), und Sie werden feststellen, dass der Index die Aufzählung für den letzten Wert ist - beim Schreiben in das Wörterbuch überschreiben Sie die Werte. Aber es hat mir genug gegeben, um dorthin zu gelangen, denke ich. Ich verstehe Ihren Code und da ich wirklich ein Lexikon des Schlüssels erstellen möchte: Wert Ende: Wert Ich bin da. – PyNEwbie

+0

Ich habe die Lösung erweitert, um Ihr Problem zu lösen –

0

Wenn ich denke, das ist, was Sie fragen ...

l = ['asd', 'asdxzc'] 
d = {} 

for i, x in enumerate(l): 
    d[x] = {'index': i} 
+3

Warum verwenden Sie nicht für das aufzählen? –

+0

Wusste nicht, dass es existiert. Macht es ein bisschen einfacher. –

+0

Ihr Code einfach erhält den Indexwert jedes eindeutigen Elements in der Liste, ich möchte den Indexwert ein wenig feiner erhalten. Nadias Code hat eine saubere Antwort. Ich glaube nicht, dass es eine bessere Lösung geben wird. – PyNEwbie

Verwandte Themen