Seite 1 von 1

Liste in Sublisten unterteilen

Verfasst: Montag 15. September 2014, 14:40
von mathematik
Hallo zusammen,

ich habe folgendes Problem:
meine Liste A enthält eine aufsteigende Folge von Zahlen, die aber nicht notwendigerweise aufeinander folgen.

Code: Alles auswählen

A=[1,2,4,5,6,7,10,15,16,17,19,20] 
diese Liste möchte ich nun in Sublisten zerlegen, so dass in jeder Subliste aufeinanderfolgende Zahlen enthalten sind. Sobald eine Reihe abbricht, will ich eine neue Subliste haben. Also:

Code: Alles auswählen

A=[[1,2],[4,5,6,7],[10],[15,16,17],[19,20]]
Wie kann ich so etwas möglichst geschickt machen? Wenn ich eine immer gleiche Anzahl and aufeinanderfolgenden Zahlen hätte, wäre das kein Problem. Für mein Problem hatte ich mir überlegt immer aufeinanderfolgede Zahlen als Zweierpaare zu nehmen und diese nur dann zu speichern, wenn sie aufeinander folgen und das ganze dann mit zwei Zweierpaaren usw. Dies ist allerdings ziemlich uneffektiv, wenn ich lange Listen habe...

Vielen Dank!

Re: Liste in Sublisten unterteilen

Verfasst: Montag 15. September 2014, 15:21
von Sirius3
@mathematik: Deine Problembeschreibung enthält doch gar keine Zweierpaare, sondern nur eine Zahl und ihren Vorgänger. Wie würdest Du das Vorgehen in Worten beschreiben: Für jede Zahl in einer Liste, nehme diese Zahl und ...

Re: Liste in Sublisten unterteilen

Verfasst: Montag 15. September 2014, 15:33
von /me
mathematik hat geschrieben:Wie kann ich so etwas möglichst geschickt machen?
Mit itertools. Alle coolen Dinge gehen mit itertools. :mrgreen:

Code: Alles auswählen

from itertools import count, groupby

data = [1, 2, 4, 5, 6, 7, 10, 15, 16, 17, 19, 20]
result = [list(value) for _, value in groupby(data, lambda value, c=count(): value - next(c))]
print(result)
groupby sollte man sich auf jeden Fall mal ansehen und damit experimentieren. Der lambda-Ausdruck ist gar nicht so dramatisch wie er vielleicht auf den ersten Blick aussieht. Im Endeffekt erzeugt er nur das Schlüsselkriterium für die Gruppierung. In diesem Fall ist es die Differenz des jeweiligen Wertes zu einem mitlaufenden Zähler. Solange der Abstand der aufeinander folgenden Werte 1 ist gehören sie zu einer Gruppe. Ist der Abstand größer oder kleiner so beginnt eine neue Gruppe.

Sollte das im ersten Moment etwas überwältigend wirken, so kann man sich mit folgendem Code anschauen wie das Gruppierungskriterium gebildet wird.

Code: Alles auswählen

data = [1, 2, 4, 5, 6, 7, 10, 15, 16, 17, 19, 20]
for value, counter in zip(data, count()):
    print('value - counter: {} - {} = {}'.format(value, counter, value - counter))
Ergebnis

Code: Alles auswählen

value - counter: 1 - 0 = 1
value - counter: 2 - 1 = 1
value - counter: 4 - 2 = 2
value - counter: 5 - 3 = 2
value - counter: 6 - 4 = 2
value - counter: 7 - 5 = 2
value - counter: 10 - 6 = 4
value - counter: 15 - 7 = 8
[...]

Re: Liste in Sublisten unterteilen

Verfasst: Montag 15. September 2014, 16:15
von mathematik
Oh vielen Dank /me!
Itertools sollte ich mir doch glatt mal merken, wenn man damit alle coolen Sachen macht! :)
Und jetzt gehts ans rumspielen mit groupby :D

@Sirius3: Ich hätte mein Vorgehen folgendermaßen beschrieben:
Erster Schritt: Für jede Zahl in einer Liste, nehme diese Zahl und die auf diese folgende Zahl. Wenn die Differenz beider Zahlen 1 ist, erstelle eine Sublist aus diesen beiden Zahlen. (Damit würden dann einzeln stehende Zahlen herausfallen, was mich für meine weiteren Analysen nicht stört....)
Zweiter Schritt: Nun überprüfe für alle Sublisten, ob der letzte Eintrag einer Subliste gleich dem ersten Einrag der folgenden Subliste ist. Ist dies der Fall, fasse beide Sublisten zusammen. Wenn nicht, erhalte die Subliste.
usw.
Dies ist aber vermutlich deutlich aufwändiger als itertools. Deshalb werd ich mich diesem widmen.

Re: Liste in Sublisten unterteilen

Verfasst: Montag 15. September 2014, 16:34
von /me
mathematik hat geschrieben:Dies ist aber vermutlich deutlich aufwändiger als itertools.
So ganz spontan könnte das etwa auf den folgenden Code hinauslaufen.

Code: Alles auswählen

data = [1, 2, 4, 5, 6, 7, 10, 15, 16, 17, 19, 20]
new_data = []
sublist = []
last_value = data[0]
for value in data:
    if value - last_value != 1:
        if sublist:
            new_data.append(sublist)
        sublist = [value]
    else:
        sublist.append(value)
    last_value = value
new_data.append(sublist)
print(new_data)
Es wird jeder Wert der Liste durchlaufen und ermittelt, ob die Differenz zwischen aktuellem Wert und folgendem Wert ungleich 1 ist. Wenn das der Fall ist wird die bestehende Subliste der Liste hinzugefügt und eine neue Subliste erstellt. Ist die Differenz 1, dann wird der Wert an die existierende Subliste angehängt. Die letzte Subliste muss man dann noch außerhalb der Schleife hinzufügen.

groupby macht eigentlich das gleiche, nur handlicher.

Re: Liste in Sublisten unterteilen

Verfasst: Montag 15. September 2014, 16:53
von Sirius3
@/me: jetzt hast Du meine Hausaufgaben für mathematik gemacht :P

Man kann das ganze natürlich noch etwas kompakter schreiben:

Code: Alles auswählen

data = [1, 2, 4, 5, 6, 7, 10, 15, 16, 17, 19, 20]
new_data = [[data[0]]]
for value in data[1:]:
    if value - new_data[-1][-1] != 1:
        new_data.append([])
    new_data[-1].append(value)

Re: Liste in Sublisten unterteilen

Verfasst: Montag 15. September 2014, 17:53
von EyDu
Unlesbar, aber mit reduce :D

Code: Alles auswählen

reduce(
    lambda x, y: x[:-1] + [x[-1] + [y]] if x[-1][-1] + 1 == y else x + [[y]],
    data[1:],
    [[data[0]]])
Hat natürlich ein "kleines" Problem mit leeren Listen.

Re: Liste in Sublisten unterteilen

Verfasst: Montag 15. September 2014, 21:29
von /me
Sirius3 hat geschrieben:Man kann das ganze natürlich noch etwas kompakter schreiben:
Aber das ist doch dann gar nicht mehr so umständlich ... :wink: