2012-05-10 14 views
38

Ho una lista di numeri e voglio ottenere il numero di volte in cui un numero appare in un elenco che soddisfa determinati criteri. Posso usare una comprensione di lista (o una comprensione di lista in una funzione) ma mi chiedo se qualcuno ha un modo più breve.numero di valori in un elenco maggiore di un certo numero

# list of numbers 
j=[4,5,6,7,1,3,7,5] 
#list comprehension of values of j > 5 
x = [i for i in j if i>5] 
#value of x 
len(x) 

#or function version 
def length_of_list(list_of_numbers, number): 
    x = [i for i in list_of_numbers if j > number] 
    return len(x) 
length_of_list(j, 5) 

c'è una versione ancora più condensata?

risposta

80

Si potrebbe fare qualcosa di simile:

>>> j = [4, 5, 6, 7, 1, 3, 7, 5] 
>>> sum(i > 5 for i in j) 
3 

Si potrebbe inizialmente sembrare strano per aggiungere True-True in questo modo, ma non credo che sia unpythonic; dopo tutto, boolis a subclass di int in tutte le versioni dal 2.3:

>>> issubclass(bool, int) 
True 
+0

+1 Questa è davvero una buona soluzione. – jamylak

+1

@jamylak, perché è meglio di quello di Greg Hewgill? Sebbene sia interessante e corretto, sembra molto meno intuitivo e meno ovvio per chi legge il codice. – TJD

+1

@TJD Non ho detto che era meglio, ma mi piace di più. – jamylak

7

se si sta utilizzando in altro modo NumPy, è possibile salvare un paio di colpi, ma io non credo che diventa molto più veloce/compatto di risposta di senderle.

import numpy as np 
j = np.array(j) 
sum(j > i) 
9

È possibile creare un risultato intermedio più piccolo come questo:

>>> j = [4, 5, 6, 7, 1, 3, 7, 5] 
>>> len([1 for i in j if i > 5]) 
3 
+8

Oppure 'sum (1 per i in j se i> 5)' quindi non è necessario caricare l'elenco in memoria. – jamylak

3

A (un po ') modo diverso:

reduce(lambda acc, x: acc + (1 if x > 5 else 0), j, 0)

1

Se si utilizza NumPy (come nella risposta di ludaavic), per array di grandi dimensioni probabilmente si vorrà usare la funzione sum di NumPy piuttosto che l'incorporata di Python sum per un significativo aumento della velocità, ad es. a> 1000x aumento di velocità per 10 milioni array elemento sul mio portatile:

>>> import numpy as np 
>>> ten_million = 10 * 1000 * 1000 
>>> x, y = (np.random.randn(ten_million) for _ in range(2)) 
>>> %timeit sum(x > y) # time Python builtin sum function 
1 loops, best of 3: 24.3 s per loop 
>>> %timeit (x > y).sum() # wow, that was really slow! time NumPy sum method 
10 loops, best of 3: 18.7 ms per loop 
>>> %timeit np.sum(x > y) # time NumPy sum function 
10 loops, best of 3: 18.8 ms per loop 

(sopra usa %timeit "magia" di IPython per timing)

1

modo diverso di conteggio utilizzando tagliare in due moduli:

>>> from bisect import bisect 
>>> j = [4, 5, 6, 7, 1, 3, 7, 5] 
>>> j.sort() 
>>> b = 5 
>>> index = bisect(j,b) #Find that index value 
>>> print len(j)-index 
3 
Problemi correlati