2013-08-04 14 views
5

Ho un elenco 2D, ad esempio mylist =[[1,2,3],[4,5,6],[7,8,9]].Lunghezza dell'elenco 2d in python

Esiste un modo per utilizzare la funzione len() in modo da poter calcolare le lunghezze degli indici di array? Per esempio:

len(mylist[0:3]) 
len(mylist[1:3]) 
len(mylist[0:1]) 

dovrebbe dare:

9 
6 
3 

risposta

4

length = sum([len(arr) for arr in mylist])

sum([len(arr) for arr in mylist[0:3]]) = 9 
sum([len(arr) for arr in mylist[1:3]]) = 6 
sum([len(arr) for arr in mylist[2:3]]) = 3 

Somma della lunghezza di eac h lista in mylist per ottenere la lunghezza di tutti gli elementi.
Funzionerà correttamente solo se l'elenco è 2D. Se alcuni elementi di mylist non sono liste, chissà cosa accadrà ...

Inoltre, è possibile associare questo ad una funzione:

len2 = lambda l: sum([len(x) for x in l]) 
len2(mylist[0:3]) = 9 
len2(mylist[1:3]) = 6 
len2(mylist[2:3]) = 3 
+2

Non è necessario utilizzare un elenco di comprensione. Un generatore è più veloce. – Blender

+0

Di una comprensione di lista? Ho difficoltà a credere che ... –

+1

@ MattBryant Naturalmente. 'sum (len (arr) per arr in mylist [0: 3])' è più veloce di 'sum ([len (arr) per arr in mylist [0: 3]])' – TerryA

2

È possibile appiattire la lista, quindi chiamare len su di esso:

>>> mylist=[[1,2,3],[4,5,6],[7,8,9]] 
>>> import collections 
>>> def flatten(l): 
...  for el in l: 
...   if isinstance(el, collections.Iterable) and not isinstance(el, basestring): 
...    for sub in flatten(el): 
...     yield sub 
...   else: 
...    yield el 
... 
>>> len(list(flatten(mylist))) 
9 
>>> len(list(flatten(mylist[1:3]))) 
6 
>>> len(list(flatten(mylist[0:1]))) 
3 
0

come su len(ast.flatten(lst))? funziona solo in py2k afaik

E '

from compiler import ast 
len(ast.flatten(lst)) 

dal

ast.flatten([1,2,3]) == [1,2,3] 
ast.flatten(mylist[0:2]) == [1,2,3,4,5,6] 
ast.flatten(mylist) == [1,2,3,4,5,6,7,8,9] 
2

È possibile utilizzare reduce per calcolare la lunghezza di indici di array come questo, questo può anche gestire lo scenario quando si passa a qualcosa di Mi piace mylist[0:0]:

def myLen(myList): 
    return reduce(lambda x, y:x+y, [len(x) for x in myList], 0) 

myLen(mylist[0:3]) = 9 
myLen(mylist[1:3]) = 6 
myLen(mylist[0:1]) = 3 
myLen(mylist[0:0]) = 0 
2

Mi piace @Ha la risposta di idro, che funziona per il nesting arbitrario, ma non mi piace la creazione della lista intermedia. Ecco una variante che evita questo.

try: 
    reduce 
except NameError: 
    # python3 - reduce is in functools, there is no basestring 
    from functools import reduce 
    basestring = str 

import operator 
import collections 

def rlen(item): 
    """ 
    rlen - recursive len(), where the "length" of a non-iterable 
    is just 1, but the length of anything else is the sum of the 
    lengths of its sub-items. 
    """ 
    if isinstance(item, collections.Iterable): 
     # A basestring is an Iterable that contains basestrings, 
     # i.e., it's endlessly recursive unless we short circuit 
     # here. 
     if isinstance(item, basestring): 
      return len(item) 
     return reduce(operator.add, (rlen(x) for x in item), 0) 
    return 1 

Per il gusto di farlo ho incluso un generatore-driven, completamente ricorsiva flatten pure. Nota che questa volta c'è una decisione più difficile da prendere sulle stringhe (il cortocircuito sopra è banalmente corretto dal len(some_string) == sum(len(char) for char in some_string)).

def flatten(item, keep_strings=False): 
    """ 
    Recursively flatten an iterable into a series of items. If given 
    an already flat item, just returns it. 
    """ 
    if isinstance(item, collections.Iterable): 
     # We may want to flatten strings too, but when they're 
     # length 1 we have to terminate recursion no matter what. 
     if isinstance(item, basestring) and (len(item) == 1 or keep_strings): 
      yield item 
     else: 
      for elem in item: 
       for sub in flatten(elem, keep_strings): 
        yield sub 
    else: 
     yield item 

Se non è necessario arbitraria di nidificazione, se siete sempre sicuri che questo è solo una lista di liste (o lista di tuple, tuple di liste, ecc) -Il metodo "migliore" è probabilmente la semplice variante "somma del generatore" della risposta di @Matt Bryant:

len2 = lambda lst: sum(len(x) for x in lst)