2013-08-04 12 views
5

Mam listę 2D, na przykład mylist =[[1,2,3],[4,5,6],[7,8,9]].Długość listy 2d w pytonie

Czy istnieje sposób, w jaki mogę korzystać z funkcji len() w taki sposób, że mogę obliczyć długości indeksów tablicy? Na przykład:

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

Należy podać:

9 
6 
3 

Odpowiedz

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 

Suma długości z eac h lista w mylist, aby uzyskać długość wszystkich elementów.
To będzie działać poprawnie, jeśli lista jest 2D. Jeśli niektóre elementy mylist nie są listy, kto wie, co się stanie ...

Dodatkowo, można to wiązać z funkcją:

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

Nie trzeba używać rozumienia list. Generator jest szybszy. – Blender

+0

Niż lista rozumienia? Trudno mi uwierzyć, że ... –

+1

@MattBryant Oczywiście. 'sum (len (arr) dla arr w mylist [0: 3])' jest szybszy niż 'suma ([len (arr) dla arr w mojej liście [0: 3]])' – TerryA

2

można spłaszczyć listy, a następnie zadzwonić len na nim:

>>> 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

jak o len(ast.flatten(lst))? działa tylko w py2k AFAIK

To

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

od

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

Można użyć reduce obliczyć długość indeksów tablicy, takich jak ten, może również obsługiwać scenariusz kiedy przechodzą w czymś jak 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

Lubię @Ha Odpowiedź idro, która działa dla dowolnego zagnieżdżenia, ale nie podoba mi się stworzenie listy pośredniej. Oto wariant, który tego unika.

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 

Do cholery z tym podaję generator napędzany, w pełni rekurencyjne flatten również. Zauważ, że tym razem jest trudniej podjąć decyzję o napisach (powyższe zwarcie jest trywialnie poprawne, ponieważ jako 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 

Jeśli nie trzeba arbitralne zagnieżdżanie-jeśli jesteś zawsze upewnić się, że jest to po prostu listę list (lub listę krotek, krotki list, etc) -the „najlepsza” metoda jest prawdopodobnie prosty wariant "suma generatora" @Matt Bryant's odpowiedź:

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