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)
Non è necessario utilizzare un elenco di comprensione. Un generatore è più veloce. – Blender
Di una comprensione di lista? Ho difficoltà a credere che ... –
@ MattBryant Naturalmente. 'sum (len (arr) per arr in mylist [0: 3])' è più veloce di 'sum ([len (arr) per arr in mylist [0: 3]])' – TerryA