2010-11-03 16 views
1

Compte tenu de ces 2 listesÉlimine dups et somme termes correspondants dans les listes

L2 = [A,B,C,D,A,B] 
L3 = [3,2,1,2,2,1] 

Je veux obtenir

L2_WANTED = [A,B,C,D] 
L3_WANTED = [5,3,1,2] 

Les listes sont toujours commandés et même taille et les éléments correspondent comme paires de valeurs clés, par exemple A : 3, B: 2 et ainsi de suite.

L'objectif est d'éliminer les doublons dans L2 et de sommer les termes correspondants dans L3 pour obtenir une nouvelle liste avec des paires correspondantes. Cela permet de conserver une liste courante d'éléments lorsqu'ils sont ajoutés aux listes.

J'ai essayé d'écrire une fonction avec index mais elle a commencé à devenir moche. J'ai vérifié itertools mais je n'ai rien trouvé de pertinent; J'ai regardé starmap() mais je ne pouvais pas le faire fonctionner. Probablement cela peut être fait avec la compréhension de la liste aussi bien. J'apprécierais n'importe quels indices ou directions sur la façon d'accomplir cette manière la plus simple. Je vous remercie.

modifier

@SimonC:

>>> l2_sum = {} 
>>> for i in range(0, len(L2)): 
     key = L2[i] 
     num = L3[i] 
     l2_sum[key] = l2_sum.get(key, 0) + num 


>>> l2_sum 
{'A': 5, 'C': 1, 'B': 3, 'D': 2} 
>>> 

Comment cela élimine les dupes et ajoutez les chiffres? Pouvez-vous donner un indice? Merci.

Répondre

2

Je suis sûr qu'il y a plus de réponse élégante là et viendrait dans les réponses.

Mais pour quelques réponses simples:

L2 = ['A','B','C','D','A','B'] 
L3 = [3,2,1,2,2,1] 

L4 = zip(L2, L3) 

L5 = [] 
L6 = [] 
def freduce(l): 
    for x, y in l: 
     print x , y 
     if x in L5: 
      k = L5.index(x) 
      L6[k] += y 
     else: 
      L5.append(x) 
      L6.append(y) 

freduce(L4) 
print L5 
print L6 

Sortie:

['A', 'B', 'C', 'D'] 
[5, 3, 1, 2] 

[Edité réponse pour la compréhension de la deuxième mise en œuvre]

>>> L3 = [3,2,1,2,2,1] 
>>> L2 = ['A','B','C','D','A','B'] 
>>> range(0, len(L2)) 
[0, 1, 2, 3, 4, 5] 
>>> 

Par conséquent, dans pour i dans la gamme (0 , len (L2)): ... i devient un index

En utilisant cet index, vous pouvez extraire des informations de L3 et L2 en faisant:

key = L2[i] 
num = L3[i] 

Ensuite, vous ajoutez des informations à la dict

l2_sum[key] = l2_sum.get(key, 0) + num 

Ici l2_sum.get (touche, 0) renvoie 0 si la clé n'est pas présente sinon la valeur actuelle.

J'espère que c'est assez clair.

+0

Cela me semble élégant! Merci beaucoup. – Zeynel

+0

Je n'essaie pas d'être inflammatoire, mais je pense que ma réponse est légèrement plus claire dans son intention. Même si c'est peut-être parce que je viens d'un contexte plus procédural et que la programmation fonctionnelle me fait mal à la tête ... – SimonC

+0

Merci. Oui je suis d'accord. J'ai juste eu l'occasion de le regarder et j'ai édité ma question si vous voulez jeter un coup d'oeil. – Zeynel

1

Cela le fera, mais par pyfunc, il y a de meilleures façons:

l2_sum = {} 
for i in range(0,len(L2)): 
    key = L2[i] 
    num = L3[i] 
    l2_sum[key] = l2_sum.get(key, 0) + num 

L2_WANTED = sorted(l2_sum.keys()) 
L3_WANTED = [l2_sum[key] for key in L2_WANTED] 
+0

Merci pour la réponse. Je vais regarder cela plus attentivement demain, mais un essai rapide dans IDLE donne une erreur: ' TypeError: type (s) d'opérande non supporté (s) pour +: 'int' et 'str'' (c'est peut-être mon erreur) – Zeynel

+0

Mes définitions de L2 et L3 ressemblent à: L2 = ['A', 'B', 'C', 'D', 'A', 'B'] L3 = [3,2,1,2,2 , 1] – SimonC

+0

Désolé, en appuyant sur enter, il semble que vous ayez posté le commentaire ... Je voulais ajouter que vous devrez changer en 'num = int (L3 [i])' si votre liste L3 contient des chaînes. – SimonC

2

Je pense que l'utilisation zip est une bonne façon de combiner les listes.La partie dict.update fera le sommateur depuis que je récupérer la valeur précédente et le mettre à jour:

foo = dict() 
for x, y in zip(['A', 'B', 'C', 'D', 'A', 'B'], 
       [3, 2, 1, 2, 2, 1]): 
    foo[x] = y + foo.get(x, 0) 

print foo 

Sorties: {'A': 5, 'C': 1, 'B': 3, 'D': 2}

Edit:

Bien que ce qui précède est très bien, je voudrais aussi envisager d'utiliser itertools.izip qui vous permet de faire le zip pendant que vous construisez le dictionnaire. De cette façon, vous économiserez de la mémoire. Tout ce que vous devez faire est de remplacer zip par itertools.izip après l'importation iterools

+0

agréable et avec un OrderedDict http://docs.python.org/library/collections.html?#collections.OrderedDict vous obtenez la commande aussi! –

+0

Totalement! Je pense que j'envisagerais d'utiliser izip aussi, donc vous n'avez pas besoin de calculer le zip entier en premier. – dcolish

+0

tu 'foo.update ({x: y + foo.get (x, 0)})' est une sorte de wierd, 'foo [x] = foo.get (x, 0)} est simple. –