2011-04-29 32 views
15

Deseo obtener el número de veces que x aparece en la lista anidada.Lista anidada y recuento()

si la lista es:

list = [1, 2, 1, 1, 4] 
list.count(1) 
>>3 

Esto está bien. Pero si la lista es:

list = [[1, 2, 3],[1, 1, 1]] 

¿Cómo puedo obtener el número de veces que aparece 1? En este caso, 4.

+3

aplanar primera. Buscar alrededor –

Respuesta

9

Aquí hay otro enfoque para aplanar una secuencia anidada. Una vez que la secuencia se aplana, es una comprobación fácil de encontrar la cantidad de elementos.

def flatten(seq,container=None): 
    if container is None: 
     container = [] 
    for s in seq: 
     if hasattr(s,'__iter__'): 
      flatten(s,container) 
     else: 
      container.append(s) 
    return container 


c = flatten([(1,2),(3,4),(5,[6,7,['a','b']]),['c','d',('e',['f','g','h'])]]) 
print c 
print c.count('g') 

d = flatten([[[1,(1,),((1,(1,))), [1,[1,[1,[1]]]], 1, [1, [1, (1,)]]]]]) 
print d 
print d.count(1) 

El anterior código imprime:

[1, 2, 3, 4, 5, 6, 7, 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h'] 
1 
[1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1] 
12 
5

Prueba esto:

reduce(lambda x,y: x+y,list,[]).count(1) 

Básicamente, se empieza con una lista vacía [] y añadir cada elemento de la lista list a ella. En este caso, los elementos son listas y obtienes una lista aplanada.

PD: ¡Acabo de recibir una respuesta similar en otra pregunta!

PPS: ¡Acabo de recibir una votación negativa para esta solución también!

+0

Esto no funcionará con anidamiento arbitrario. -1 –

+5

Las personas bajan arbitrariamente aquí. Voto a favor de soluciones de mierda. El mío definitivamente no lo es. Y no se menciona ninguna anidación arbitraria y funciona para el caso del OP. No más de pensar. – manojlds

+0

Sí, porque se niega a dar un paso más y proporciona más información sobre el problema más profundo y cómo encontrar una solución más general. –

8

itertools y collections módulos tiene sólo el material que necesita (aplanar las listas anidadas con itertools.chain y contar con collections.Counter

import itertools, collections 

data = [[1,2,3],[1,1,1]] 
counter = collections.Counter(itertools.chain(*data)) 
print counter[1] 

Utilice una función aplanar recursiva en lugar de itertools.chain para aplanar las listas anidadas de nivel de profundidad arbitraria

import operator, collections 

def flatten(lst): 
    return reduce(operator.iadd, (flatten(i) if isinstance(i, collections.Sequence) else [i] for i in lst)) 

reduce con operator.iadd se ha usado en lugar de sum para que el plano Ned se construye una sola vez y se actualiza en el lugar

+0

cadena() funciona solo para anidación de 1 nivel aunque. –

+0

Se actualizó la respuesta – Imran

24
>>> L = [[1, 2, 3], [1, 1, 1]] 
>>> sum(x.count(1) for x in L) 
4 
+0

Esto no funcionará con anidamiento arbitrario. - 1 –

+13

@RestRisiko: ¿Dónde dice la pregunta que se requiere una anidación arbitraria? Tu propia respuesta sobre esta pregunta ni siquiera cubre eso, pero ¿rechazarás a otros por eso? –

+1

¿Por qué las personas votan negativamente por respuestas muy válidas? Le di un +1 por esto y me gusta mejor que mi respuesta. Pero mi respuesta no fue mala, y definitivamente, esta no es !!! – manojlds

2

Si sólo hay un nivel de aplanamiento de anidación se puede hacer con esta lista comprenension:

>>> L = [[1,2,3],[1,1,1]] 
>>> [ item for sublist in L for item in sublist ].count(1) 
4 
>>> 
4

Para el gusto de hacerlo: contar a cualquier profundidad de anidamiento arbitrario, manipulación tuplas, listas y argumentos:

hits = lambda num, *n: ((1 if e == num else 0) 
    for a in n 
     for e in (hits(num, *a) if isinstance(a, (tuple, list)) else (a,))) 

lst = [[[1,(1,),((1,(1,))), [1,[1,[1,[1]]]], 1, [1, [1, (1,)]]]]] 
print sum(hits(1, lst, 1, 1, 1)) 

15 
+1

+1 para el mejor abusador de '' lambda'' por aquí ;-). Esto también responde a la pregunta de cómo incrustar recursivamente un generador en sí mismo :-). – ThomasH

0
def nested_count(lst, x): 
    return lst.count(x) + sum(
     nested_count(l,x) for l in lst if isinstance(l,list)) 

Esta función devuelve el número de occurr ences, más el conteo anidado recursivo en todas las sublistas contenidas.

>>> data = [[1,2,3],[1,1,[1,1]]] 
>>> print nested_count(data, 1) 
5 
Cuestiones relacionadas