As compreensões da lista de Python (idealmente) podem fazer o equivalente a 'Count (*)… grupo por…' no SQL?

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

  •  23-09-2019
  •  | 
  •  

Pergunta

Acho que as compreensões da lista podem me dar isso, mas não tenho certeza: quaisquer soluções elegantes no Python (2.6) em geral para selecionar objetos exclusivos em uma lista e fornecer uma contagem?

(Eu defini um __eq__ Para definir a singularidade na minha definição de objeto).

Então, em RDBMS-Land, algo assim:

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;

Que dá:

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

Então, aqui está minha lista equivalente em Python:

[1,1,1,2]

E eu quero a mesma saída que a seleção SQL fornece acima.

EDIT: O exemplo que dei aqui foi simplificado, na verdade estou processando listas de instâncias de objetos definidas pelo usuário: apenas para completar o código extra que eu precisava para fazer com que tudo funcionasse:

import hashlib

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

o __hash__ Método era necessário para obter o set Conversão ao trabalho (optei pela ideia de compreensão de lista que funciona em 2.6 [apesar do fato de ter aprendido que envolva uma ineficiência (ver comentários) - meu conjunto de dados é pequeno o suficiente para isso não é um problema]). my_list_of_stuff Acima está uma lista de (strings) na minha definição de objeto.

Foi útil?

Solução

Lennart Regebro forneceu uma boa linha Isso faz o que você quer:

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

Como S.Lott menciona, um DefaultDict pode fazer a mesma coisa.

Outras dicas

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

Contador Somente disponível em py3.1, herda do dict.

Não facilmente facilmente como uma compreensão de lista.

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

Esta é uma solução muito pitônica. Mas não é uma compreensão da lista.

Você pode usar groupby de itertools módulo:

Faça um iterador que retorne chaves e grupos consecutivos do iterável. A chave é uma função calculando um valor de chave para cada elemento. Se não for especificado ou não for, os principais padrões para uma função de identidade e retornam o elemento inalterado. Geralmente, o iterável precisa já ser classificado na mesma função -chave.

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

Eu assumiria que seu tempo de execução é pior que o dict-Soluções baseadas em Silentghost ou S.Lott, já que ele precisa classificar a sequência de entrada, mas você deve chegar a si mesmo. É uma compreensão da lista, no entanto. Deve ser mais rápido que a solução de Adam Bernier, pois não precisa fazer varreduras lineares repetidas da sequência de entrada. Se necessário, o sorted A chamada pode ser evitada classificando a sequência de entrada em linha.

Os seguintes trabalhos em Python 2.4 e deve Portanto, trabalhe no 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"
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top