Peut liste des compréhensions de Python (idéalement) faire l'équivalent de « count (*) ... groupe par ... » dans SQL?

StackOverflow https://stackoverflow.com/questions/2148480

  •  23-09-2019
  •  | 
  •  

Question

Je pense que la liste compréhensions peut me donner, mais je ne suis pas sûr: des solutions élégantes en Python (2.6) en général pour la sélection d'objets uniques dans une liste et en fournissant un nombre

?

(je l'ai défini un __eq__ pour définir l'unicité de ma définition de l'objet).

Donc, en terre SGBDR, quelque chose comme ceci:

CREATE TABLE x(n NUMBER(1));
INSERT INTO x VALUES(1);
INSERT INTO x VALUES(1);
INSERT INTO x VALUES(1);
INSERT INTO x VALUES(2);

SELECT COUNT(*), n FROM x
GROUP BY n;

Ce qui donne:

COUNT(*) n
==========
3        1
1        2

Alors, voici ma liste équivalente en Python:

[1,1,1,2]

Et je veux la même sortie que le SQL SELECT ci-dessus donne.

EDIT: L'exemple que je donnais ici a été simplifié, je suis en fait le traitement des listes d'instances d'objets définis par l'utilisateur: juste pour être complet, j'inclure le code supplémentaire que je avais besoin de la chose au travail:

import hashlib

def __hash__(self):
    md5=hashlib.md5()
    [md5.update(i) for i in self.my_list_of_stuff]
    return int(md5.hexdigest(),16)

La méthode __hash__ était nécessaire pour obtenir la conversion de set au travail (j'ai opté pour l'idée de liste de compréhension qui fonctionne en 2.6 [en dépit du fait que j'appris cela implique un manque d'efficacité (voir les commentaires) - mon ensemble de données est assez petit pour ce pas un problème]). my_list_of_stuff ci-dessus est une liste de (Strings) sur ma définition de l'objet.

Était-ce utile?

La solution

Lennart Regebro fourni un bon one-liner qui fait ce que vous voulez:

>>> values = [1,1,1,2]
>>> print [(x,values.count(x)) for x in set(values)]
[(1, 3), (2, 1)]

Comme S. Lott mentionne , un defaultdict peut faire la même chose.

Autres conseils

>>> from collections import Counter
>>> Counter([1,1,1,2])
Counter({1: 3, 2: 1})

compteur disponible uniquement en py3.1, hérite de le dict.

Pas facilement faisables comme la compréhension de la liste.

from collections import defaultdict
def group_by( someList ):
    counts = defaultdict(int)
    for value in someList:
        counts[value.aKey] += 1
    return counts

Ceci est une solution très Pythonic. Mais pas une compréhension de la liste.

Vous pouvez utiliser groupby du module itertools:

  

Faire une iterator qui retourne les clés consécutives et les groupes de la itérables. La clé est une fonction de calcul d'une valeur de clé pour chaque élément. Si non spécifié ou est Aucun, par défaut clés à une fonction d'identité et renvoie l'élément inchangé. En général, le itérables doit être triée déjà sur la même touche de fonction.

>>> a = [1,1,1,2]
>>> [(len(list(v)), key) for (key, v) in itertools.groupby(sorted(a))]
[(3, 1), (1, 2)]

Je suppose que son exécution est pire que les solutions basées sur dict par-SilentGhost ou S. Lott, car il doit trier la séquence d'entrée, mais vous devriez temps qui vous. Il est une compréhension de la liste, cependant. Il devrait être plus rapide que la solution d'Adam Bernier, car il n'a pas à faire des analyses linéaires répétées de la séquence d'entrée. En cas de besoin, l'appel sorted peut être évité en triant la séquence d'entrée en ligne.

Les travaux suivants en Python 2.4 et devraient donc travailler en Python 2.6:

lst = [1,1,2,2,3,4,5,6,5]
lst_tmp = []
lst_dups = []

for item in lst:
    if item in lst_tmp:
        lst_dups.append(item)
    else:
        lst_tmp.append(item)

if len(lst_dups):
    lst_dups = sorted(set(lst_dups))
    for item in lst_dups:
        print str(lst.count(item)), "instances of", item
else:
    print "list is unique"
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top