2009-05-27 8 views
1

J'ai cherché une recette/exemple pour indexer une liste de tuples sans modifier l'approche de décorer, trier, sans décor.Y at-il un moyen en Python d'indexer une liste de conteneurs (tuples, listes, dictionnaires) par un élément d'un conteneur?

Par exemple:

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

L'approche que je l'ai utilisé est de construire un dictionnaire à l'aide defaultdict du second élément

from collections import defaultdict 

tdict=defaultdict(int) 

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

Ensuite, je dois construire une liste constituée de la deuxième élément dans le tuple pour chaque élément de la liste. Bien qu'il existe plusieurs façons d'y arriver une approche simple consiste à:

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

puis générer un index de chaque élément tdict

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

Il est clair que cela ne semble pas très Pythonic. J'ai essayé de trouver des exemples ou des idées en pensant que je devrais être capable d'utiliser quelque chose de magique pour obtenir l'index directement. Pas de chance pour le moment. Notez, je comprends que je peux prendre mon approche un peu plus directement et ne pas générer tdict.

sortie pourrait être un dictionnaire avec l'index

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

Après avoir appris beaucoup de réponses de Nadia Je pense que la réponse est non.

Pendant que sa réponse fonctionne, je pense que c'est plus compliqué que nécessaire. Je voudrais simplement

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

Je suis confus sur ce que vous essayez de faire. Quelle est votre sortie désirée? Votre code ne fonctionne pas tout à fait - ce qui est censé être dans la ligne "tdict [myTuple [1]] + = count"? –

+0

Pouvez-vous donner un exemple de la sortie ou de la structure attendue? –

+0

Désolé - chaque fois que je crée un dictionnaire pour obtenir le compte d'un élément, j'écris toujours + = count avant de le corriger à + = 1. J'ai une cellule cérébrale. – PyNEwbie

Répondre

5

Cela va générer le résultat que vous voulez

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} 

Et si vous insistez sur l'utilisation d'un dictionnaire pour représenter l'index:

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

Le résultat sera:

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

EDIT Si vous voulez gérer la collision clé, vous devrez étendre la solution comme ceci:

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

Et plus généralisé et compact solution (dans une définition similaire à 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} 

Donc la réponse à votre question est oui: Il existe un moyen en Python d'indexer une liste de conteneurs (tuples, listes, dictionnaires) par un élément d'un conteneur sans pré-traitement. Mais votre demande de stocker le résultat dans un dictionnaire rend impossible d'être un seul doublure. Mais il n'y a pas de pré-traitement ici. La liste n'est itérée qu'une seule fois.

+0

C'est glissant. Je vois est une question de réflexion sur le problème. Je vois que cela devrait généraliser à tout sous-conteneur dans une liste de conteneurs. Cool et merci – PyNEwbie

+0

En fait Nadia c'est proche mais pas tout à fait là. Essayez d'ajouter un autre tuple avec une valeur centrale commune, disons add (2,4,6) et vous verrez que l'index est l'énumération de la dernière valeur - lorsque vous écrivez dans le dictionnaire, vous écrasez les valeurs. Mais ça m'a donné assez pour y arriver je pense. Je comprends votre code et puisque je cherche vraiment à créer un dictionnaire de clé begin: value end: value je suis à peu près là. – PyNEwbie

+0

J'ai étendu la solution pour résoudre votre problème –

0

Si je pense que c'est ce que vous demandez ...

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

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

Pourquoi ne pas utiliser énumération pour cela? –

+0

Je ne savais pas que cela existait. Cela rend un peu plus simple. –

+0

Votre code simple obtient la valeur d'index de chaque élément unique dans la liste, je veux obtenir la valeur de l'index un peu plus finement. Le code de Nadia a une réponse propre. Je ne pense pas qu'il y aura une meilleure solution. – PyNEwbie

Questions connexes