2009-10-20 16 views
9

Czy istnieje sposób pythonowy do czeku jeśli lista (a zagnieżdżona lista z elementami & listy) jest zasadniczo pustym? Mam tu na myśli to, że puste jest to, że lista może zawierać elementy, ale są to również puste listy.Python: Jak sprawdzić, czy zagnieżdżona lista jest zasadniczo pusta?

pythonowy sposobem sprawdzenia pustą listę działa tylko na płaskiej listy:

alist = [] 
if not alist: 
    print("Empty list!") 

Na przykład, wszystkie następujące wykazy powinny być pozytywne dla pustki:

alist = [] 
blist = [alist]    # [[]] 
clist = [alist, alist, alist] # [[], [], []] 
dlist = [blist]    # [[[]]] 

Odpowiedz

8

I połączone zastosowanie isinstance() przez mrówki Aasma i all(map()) przez Stephan202, otrzymując następujące rozwiązanie. all([]) zwraca True, a funkcja polega na tym zachowaniu. Myślę, że ma to co najlepsze i jest lepsze, ponieważ nie polega na wyjątku od TypeError.

def isListEmpty(inList): 
    if isinstance(inList, list): # Is a list 
     return all(map(isListEmpty, inList)) 
    return False # Not a list 
+2

'return all (map (isListEmpty, inList)) if isinstance (inList, list) else False ':) – Stephan202

+0

Stephan202: Tak, to zmienia go w prawdziwy jednolinijkowy! Po prostu nie jest mi wygodnie z tą warunkową ekspresją Pythona. Trochę zagmatwany, ponieważ nie jest zamawiany w taki sam sposób, jak operator potoczny C ;-) –

4

nie wiem myślę, że jest to oczywisty sposób na zrobienie tego w Pythonie. Mój najlepszy przypuszczenie byłoby użyć funkcji rekurencyjnej jak ten:

def empty(li): 
    if li == []: 
     return True 
    else: 
     return all((isinstance(sli, list) and empty(sli)) for sli in li) 

all Zauważ, że przychodzi tylko z Python> = 2.5, i że nie będzie obsługiwać nieskończenie rekurencyjnych list (np a = []; a.append(a)).

+1

Miło, nigdy nie myślałem o nieskończonych listach rekurencyjnych w Pythonie.Fajnie jest zobaczyć, że można je nawet wydrukować ;-) –

+0

+1 dla infursu list rekurencyjnych. Teraz przejdź do [to pytanie] (http://stackoverflow.com/q/7674685/188595) przeczytaj o nich. –

1

prosty rekurencyjny sprawdzenie byłoby mało, i wrócić jak najszybciej, zakładamy, że wejście nie jest lista lub zawiera nie-list to nie jest pusty

def isEmpty(alist): 
    try: 
     for a in alist: 
      if not isEmpty(a): 
       return False 
    except: 
     # we will reach here if alist is not a iterator/list 
     return False 

    return True 

alist = [] 
blist = [alist]    # [[]] 
clist = [alist, alist, alist] # [[], [], []] 
dlist = [blist]    # [[[]]] 
elist = [1, isEmpty, dlist] 

if isEmpty(alist): 
    print "alist is empty" 

if isEmpty(dlist): 
    print "dlist is empty" 

if not isEmpty(elist): 
    print "elist is not empty" 

można dodatkowo poprawić, aby sprawdzić dla rekurencyjnej listy lub żadne przedmioty liście lub może być pusty dicts itp

+2

'isEmpty ([1])' zawiedzie, to dość problem (nie jest naprawdę użyteczne mieć funkcję sprawdzania pustej listy, jeśli działa tylko z listami, które są puste). –

+0

która może być dobrą logiką do sprawdzenia, czy lista nie jest pusta :) –

+0

DelRoth: Anurag prawdopodobnie naprawił problem, który skomentowałeś teraz. –

7

Prosty kod, działa na każdym iterowalny obiektu, a nie po prostu wymienia:

>>> def empty(seq): 
...  try: 
...   return all(map(empty, seq)) 
...  except TypeError: 
...   return False 
... 
>>> empty([]) 
True 
>>> empty([4]) 
False 
>>> empty([[]]) 
True 
>>> empty([[], []]) 
True 
>>> empty([[], [8]]) 
False 
>>> empty([[], (False for _ in range(0))]) 
True 
>>> empty([[], (False for _ in range(1))]) 
False 
>>> empty([[], (True for _ in range(1))]) 
False 

Kod ten sprawia, że ​​jako założenie, że wszystko, co można powtórzyć, będzie zawierało inne elementy i nie powinno być uważane za liść w "drzewie". Jeśli próba iteracji obiektu nie powiedzie się, nie jest to sekwencja, a zatem z pewnością nie jest pustą sekwencją (w ten sposób zwracana jest wartość False). Wreszcie, ten kod wykorzystuje fakt, że all zwraca True, jeśli jego argumentem jest pusta sekwencja.

+2

Złapanie wszystkich wyjątków to zła rzecz, która może powodować ukrywanie prawdziwych błędów w kodzie. –

+1

@Denis: prawidłowy punkt. Teraz zawęził to do "TypeError". – Stephan202

+2

+1 ale myślę, że 'map' nie powinno być używane w Pythonie. 'wszystko (puste (x) dla x w seq)' brzmi dla mnie o wiele ładniej ;-) –

9

Jeśli nie trzeba iterację listach, prostsze jest lepsze, więc coś jak to będzie działać:

def empty_tree(input_list): 
    """Recursively iterate through values in nested lists.""" 
    for item in input_list: 
     if not isinstance(item, list) or not empty_tree(item): 
      return False 
    return True 

jednak, że byłoby dobrze, aby oddzielić rekurencyjną iteracji, które będą najprawdopodobniej ponownego wykorzystania gdzie indziej i sprawdzanie, czy nie zwraca żadnych elementów. W ten sposób, jeśli zmienia się mechanizm iteracji, musisz wprowadzić zmianę w jednym miejscu. Na przykład, gdy potrzebujesz obsługi dowolnych iteracji zagnieżdżonych lub zagnieżdżonych.

def flatten(input_list): 
    """Recursively iterate through values in nested lists.""" 
    for item in input_list: 
     if isinstance(item, list): # Use what ever nesting condition you need here 
      for child_item in flatten(item): 
       yield child_item 
     else: 
      yield item 

def has_items(seq): 
    """Checks if an iterator has any items.""" 
    return any(1 for _ in seq) 

if not has_items(flatten(my_list)): 
    pass 
+0

Ants Asama: Najbardziej podoba mi się prostota Twojego rozwiązania! Zmieniłem twoją odpowiedź i przeniosłem proste rozwiązanie. Dzięki! :-) –

+0

dziękuję, zaoszczędziłeś mi dużo czasu na wyszukiwaniu .. wszystkie inne podejścia nie zadziałały dla mnie oprócz twojego .. thamks –

Powiązane problemy