2016-05-21 18 views
1

Ich habe eine Reihe von Listen in Listen. Die Verschachtelungstiefe wird zur Laufzeit bestimmt, und ich möchte nur auf eine bestimmte (Laufzeit entschieden) Tiefe zugreifen, um das, was auf dieser Ebene ist, beliebig zu manipulieren.Traverse verschachtelte Liste mit einzelnen für

Im Idealfall würde Ich mag Lage sein, dies zu tun, so einfach wie:

for x in access_list(nested_list, d) 
    # do stuff at nesting-depth d 

Was access_list tun soll:

>>> mylist = [[[0, 1], [2, 3]], [[4, 5], [6, 7]]] 
>>> for d in range(4): 
...  for l in access_list(mylist, d): 
...   print((d, l)) 
(0, [[[0, 1], [2, 3]], [[4, 5], [6, 7]]]) 
(1, [[[0, 1], [2, 3]]) 
(1, [[4, 5], [6, 7]]]) 
(2, [0, 1]) 
(2, [2, 3]) 
(2, [4, 5]) 
(2, [6, 7]) 
(3, 0) 
(3, 1) 
(3, 2) 
(3, 3) 
(3, 4) 
(3, 5) 
(3, 6) 
(3, 7) 

Mein Versuch erwies sich im Wesentlichen nichts zu tun:

def access_list(lists, d): 
    if not d: 
     return lists 
    return [access_list(_list, d-1) for _list in lists] 

Es gibt nur die gesamte Listenstruktur wieder zurück. Was kann ich tun, damit dies funktioniert?

+2

Zu viel Text. Die meisten Leute werden das nicht lesen, um zu antworten. Bitte stellen Sie Ihre Frage präziser. – PyNoob

+0

Ich stimme @pyNoob zu - machen Sie ein minimales Beispiel. Eingabe und erwartete Ausgabe. Der Titel der Frage ist einfach, warum braucht es so viel Text, um die Idee zu vermitteln? – timgeb

+0

Ich stimme @pyNoob zu. Sie brauchen tatsächlich eine Rekursion, also stellen Sie Ihre Frage auf den Code, der nicht funktioniert, und zeigen Sie einige Ein- und Ausgaben an. –

Antwort

6

Dieser Generator-Funktion für verschachtelte Listen arbeiten sollte und spart Speicherplatz, da es keine Liste selbst, sondern gemächlich produziert hat bauen die Elemente:

def access_list(nested_list): 
    if not isinstance(nested_list, list): 
    # if not isinstance(nested_list, (list, set)): you get the idea 
     yield nested_list 
    else: 
     for item in nested_list: 
      for x in access_list(item): 
       yield x 
      # in Python 3, you can replace that loop by: 
      # yield from access_list(item) 
    return 

> l = [1, 2, [3, [4, 5], 6]] 
> list(access_list(l)) 
[1, 2, 3, 4, 5, 6] 

Wenn Sie Zugriff auf Schachtelungstiefe wollen, wird die folgende erzeugen (item, depth) Paare:

def access_list(nested_list, d=0): 
    if not isinstance(nested_list, list): 
     yield nested_list, d 
    else: 
     for item in nested_list: 
      for x in access_list(item, d=d+1): 
       yield x 
    return 

> l = [1, 2, [3, [4, 5], 6]] 
> list(access_list(l)) 
[(1, 1), (2, 1), (3, 2), (4, 3), (5, 3), (6, 2)] 
+0

Berücksichtigen Sie, dass eine Liste sich selbst enthalten könnte, in diesem Fall würden Sie ein Set brauchen, um die Liste der gesehenen Listen zu verfolgen. – timgeb

+0

Können Sie nicht-hashbare Listen in ein Set einfügen? – schwobaseggl

+0

Nicht direkt, Sie könnten einfach ihre 'id' in ein Set setzen oder in' tuple' umwandeln. – timgeb

2

Betrachten Sie diese Lösung:

def access_list(lists, d): 
    if not d: 
     return lists 
    else: 
     return sum(access_list(lists, d-1), []) 

Zum Beispiel mit dieser Liste: l=[[[1,2],[3]],[[4],[5,[6,7]]]]:

>>> access_list(l, 0) 
[[1, 2], [3]] 
[[4], [5, [6, 7]]] 

>>> access_list(l, 1) 
[1, 2] 
[3] 
[4] 
[5, [6, 7]] 

>>> access_list(l, 1) 
1 
2 
3 
4 
5 
[6, 7] 
+2

Das Abflachen mit 'sum' macht Spaß, wenn Sie es zum ersten Mal sehen, aber es ist O (n^2). – timgeb

+0

Interessant, obwohl ich eigentlich nicht möchte, dass es so flach gemacht wird und wenn das tatsächlich O (n²) ist, würde ich lieber eine andere Methode verwenden. Es sieht jedoch wie eine nette einfache Lösung aus. – kram1032

2

Sie numpy Arrays verwenden könnten, es

import numpy 
def access_list(lists, d): 
    _lists=numpy.array(lists) 
    if not d: 
     L=[] 
     for index in range(len(_lists)): 
      L.append(_lists[index]) 
     return L 
    return _lists[:] 
4

Ziemlich nahe arbeiten kann! Versuchen Sie, die Listen in immer kleinere Teile aufzuteilen.

def access_list(x, d): 
    if d and isinstance(x, list) and x: 
     return access_list(x[0], d-1) + access_list(x[1:], d-1) 
    return [x] 

Okay, hatte gehofft, diese Ursache zu vermeiden, ist es etwas komplizierter ist, aber dies gibt die genaue Ausgabe für Sie hoffen:

def access_list(x, d): 
    def _access_list(x, d): 
     if d and isinstance(x, types.ListType) and x: 
      return access_list(x[0], d-1) + access_list(x[1:], d) 
     return [x] 
    return filter(lambda x: x, _access_list(x, d)) 
+0

Ihre Methode scheint seltsame Dinge zu tun, beginnend mit 'd = 2' – kram1032

+0

Rekursion ist komisch, stimme ich zu:/ –

+0

Also, vergessen Sie nicht, dass in Ihrem Beispiel, Schleife Iteration, nicht verschachtelte Tiefe drucken. Sie sind nicht das Gleiche. Sie müssen auswählen, ob die Funktion mit der Schleifeniteration oder der Rekursionstiefe übereinstimmen soll, ansonsten müssen Sie in separate Funktionen schreiben :) –