Problem mit Slicing Index 0 in Python?

3 Antworten

Vom Fragesteller als hilfreich ausgezeichnet

Dann slice doch mit positivem Index.

Du hast die länge der Liste und kannst das Offset von Start- und Endpunkt berechnen.


derkiesi 
Fragesteller
 16.02.2024, 16:04

nun ja, ich möchte die Möglichkeit offenlassen mit beliebiger Länge der Liste zu arbeiten

0
Destranix  16.02.2024, 16:08
@derkiesi

Dafür gibt es die "len"-Funktion. Die solltest du sowieso nutzen statt irgendwelcher magischen Nummern.

Für die übrigen Parameter solltest du auch Variablen definieren (wenn global, dann am besten mit anderer Schreibweise, beispielsweise alle in Großbuchstaben, damit man erkennt, dass das Parameter sind. Oder als Funktionsparameter mit ganz normaler Schreibweise).

Beispiel:

DEFAULT_SLICE_LENGTH = 3

def get_slices(list, start_index, count, slice_length=DEFAULT_SLICE_LENGTH):
    ...
0
derkiesi 
Fragesteller
 16.02.2024, 16:26
@Destranix

Magische Nummern? meinest du meine Liste oder meine Indices?

ich habe gerade schon mit der len-Funktion herumprobiert und auch das gewünschte Ergebniss bekommen:

Tripplet = liste[(len(liste)-5)+i:(len(liste)-2)+i]

doch leider finde ich das sehr unübersichtlich und habe es nur durch probieren herausgefunden. Mal sehen ob ich nächste Woche noch verstehe was ich hier gemacht habe :-)

0
Destranix  16.02.2024, 16:34
@derkiesi
meinest du meine Liste oder meine Indices?

Die Indices. Siehe auch:

https://de.wikipedia.org/wiki/Magische_Zahl_(Informatik)

Der dritte Punkt.

doch leider finde ich das sehr unübersichtlich und habe es nur durch probieren herausgefunden.Mmal sehen ob ich nächste Woche noch verstehe was ich hier gemacht habe :-)

Du startest bei Index "Länge - 5 + i" und endest bei Index "Länge - 2 + i".

Ohne Magic numbers wird es evtl. übersichtlicher (Ich habe auch noch mal Whitespaces eingefügt um es übersichtlicher zu machen. Parst so in Python aber evtl. nicht):

Tripplet = liste[
     (len(liste) - count + 1 - slice_length) + i
    :(len(liste) - count + 1)                + i
]

Du fängst an bei "Länge - count + 1" und holst dir einen Slice mit Länge "slice_length". Und für das nächste Stück erhöhst du Anfang und Ende um 1.

Anzumerken sei, dass natürlich vorher die Parameter überprüft werden sollen, dass die auch zulässig sind.

0
derkiesi 
Fragesteller
 16.02.2024, 20:14
@Destranix

Magische Zahl? Ha, wieder was gelernt und das nach 30 Jahren Programmiererfahrung.

Bitte was? 30 Jahre Programmiererfahrung?

Kleiner Spaß. Ich hab mal in meiner Jugend mit BASIC angefangen, und dann das Interesse verloren. Nun ist es wieder da und ich lerne Python.

Übrigens habe ich tatsächlich schon darüber nachgedacht wie ich mit solchen magischen Zahlen umgehe, denn mir wurde schon seit einiger zeit klar dass ich bei länger werdendem Code den Überblick bei meinen Variablen verliere. Bisher habe ich mir mit Komentaren geholfen, aber auch das stößt nun an seine Grenzen.

Ich Danke Dir für deine Hinweise.

PS: Ich war lange nichtmehr hier. Gibt es keinen Stern mehr oder die Auszeichnung als beste Antwort?

1
derkiesi 
Fragesteller
 16.02.2024, 23:05
@Destranix

Ich hab das jetzt etwas angepasst. So kann ich die Slicelänge und die Schleifenanzahl leicht ändern. Das die Slicelänge und die Schleifenanzahl gleich groß sind ist durchaus gewollt:

  • liste = [2, 7, 14, 18, 10, 1, 4, 17, 9, 6, 15, 13, 20]
  • # Schleife, um die jeweils letzten x_Elemente auszugeben, x=Schleifenanzahl !
  • Schleifenanzahl = 6
  • for i in range(Schleifenanzahl):
  • Startindex = (len(liste) - (2 * Schleifenanzahl - 1)) + i
  • Endindex = (len(liste) - (Schleifenanzahl - 1)) + i
  • neue_Liste = liste[Startindex:Endindex]
  • print(neue_Liste)

Ergebnisse:

  • [14, 18, 10, 1, 4, 17]
  • [18, 10, 1, 4, 17, 9]
  • [10, 1, 4, 17, 9, 6]
  • [1, 4, 17, 9, 6, 15]
  • [4, 17, 9, 6, 15, 13]
  • [17, 9, 6, 15, 13, 20]

würde man so programmieren? ist das "sauber"?

1
Destranix  17.02.2024, 08:51
@derkiesi
Bitte was? 30 Jahre Programmiererfahrung?

Ich begann schon mich zu wundern ;-)

Ich war lange nichtmehr hier. Gibt es keinen Stern mehr oder die Auszeichnung als beste Antwort?

Doch. Aber die kannst du erst nach 24h vergeben.

würde man so programmieren? ist das "sauber"?

Nun, man würde wohl auf jeden Fall eine oder mehrere Funktionen dafür schreiben. Gab es bei BASIC iirc noch nicht.

Klassen würden hier noch nicht so viel Sinn machen, aber davon hast du in Python auch nicht viele, da sind das nur Sammlungen von Funktionen im Prinzip.

Deine Bezeichner solltest du am besten anders ausschreiben abhängig davon, ob es Variablen sind oder Konstanten. Und ansonsten möglichst gleich. Du schreibst "liste" klein, aber "Startindex" groß und "Schleifenanzahl" auch groß.
Besser wäre wohl:

  • Wenn die Variable konstant sein soll bzw. ein Parameter, das im Code gesetzt wird, dann alles in Großbuchstaben. Beispiel: SCHLEIFENANZAHL, ZWEI_WÖRTER, ...
  • Ansonsten die variablen klein schreiben: liste, start_index, ... Oder im Camel-Case: liste, startIndex, ...

Oder du denkst dir selber soetwas aus. Hauptsache konsistent. Und am besten so, wie es andere auch machen.

Zudem solltest du noch prüfen, ob dein Parameter valide ist. Wenn man in deinem Programm die Liste gleich lässt, aber die Schleifenanzahl auf 8 setzt, dann geht es kaputt beispielsweise.
Wäre jetzt nicht so wichtig, wenn das direkt offensichtlich wäre und nur hobbymäßiger Code. Aber an sich sollte man das schon prüfen oder in Kommentaren dazuschreiben.

Ansonsten sollte das passen. Die Kommentare könnten vielleicht noch etwas ausführlicher sein.

Noch als Hinweis: Oben im Tt-Menü kannst du Text als Code formattieren.

Ein Beispiel, wie man es ganz ordentlich machen könnte:

#Gibt die letzten anzahl Teillisten der Liste mit Länge anzahl aus. anzahl muss kleiner als wasweißich sein. (Und evtl. weitere Hinweise zu den Parametern)
def slice_ende(liste, anzahl):
    if (anzahl >= len(liste//2)):#Oder soetwas
        raise ValueError("anzahl muss kleiner sein als wasweißich") # Du kannst auch irgendwie anders einen fehler signalisieren oder was anderes tun, beispielsweise das Parameter anpassen.
    for i in range(anzahl):
        startIndex = (len(liste) - (2 * anzahl - 1)) + i
        endIndex= (len(liste) - (anzahl - 1)) + i

        neueListe = liste[startIndex:endIndex]
        print(neueListe)

Bzw. evtl. würdest du sogar eine allgemeinere Funktion schreiben, die dir beliebige Slices zurückgibt und dann eine speziellere Funktion, die dann die allgemeinere ausgibt.
Und man kann noch ne Menge anderes Zeug nutzen, Iteratoren und soetwas, dass es dir dann jeweils den nächsten Wert aus der Funktion zurückgibt, ...
Aber ich denke das wäre für den Anfang etwas kompliziert.

1

Mit negativen Indizes kann das nicht klappen, weil Du damit nicht das Ende der Liste (bei „−0“) adressieren kannst. Du könntest höchstens einen Dummy an die Liste anhängen. Dann liegen die letzte Tripel bei [−6:−3], [−5:−2] und [−4:−1].


derkiesi 
Fragesteller
 16.02.2024, 19:59

Ja das hab ich nun auch gelernt. Das mit dem Dummy ist ein interessanter Gedanke, mal sehen ob ich den weiterverfolge. vielen Dank

0
for i in range(3):
   Tripplet = liste[-5 + i:-2+i]

Überleg dir nochmal, wie die Indizes aussehen müssen. Du musst ja für jedes Triplet 3 Positionen weiter nach links. Da muss also zwangsläufig eine Multiplikation in die Rechnung rein.

Wenn du dein Range so verwenden willst, wie es dasteht, geht es von 0 bis 2. Also schaut die Indexberechnung für das Slicing so aus:

for i in range(3):
   liste[-3*(i+1):len(liste)-i*3]

Ob das so der eleganteste Weg ist, bezweifle ich trotzdem.


derkiesi 
Fragesteller
 16.02.2024, 16:28

nein, ich will je Schleifendurchlauf nur eine Position weiter

0
jo135  16.02.2024, 16:33
@derkiesi

Dann habe ich deine Aufgabenstellung nicht gut gelesen, aber das ändert am Prinzip gar nicht viel: auch dann musst du eine fixe Zahl an Positionen "mal i" weitergehen. In diesem Fall halt i*1 statt i*3.

Es hilft, sich solche Dinge auf Papier aufzumalen.

Wenn du die Liste verändern darfst, ist die Lösung übrigens noch um einiges simpler, weil du dann einfach in jedem Schritt das letzte Element abschneiden kannst.

0
derkiesi 
Fragesteller
 16.02.2024, 19:54
@jo135

wenn ich die schleifenvariable i mit 1 multipliziere dann bleibt diese gleich i. Das führt also zu nichts.

Glaub mir, ich habe schon einige A4 Seite vollgemalt um das Slicing in Schleifen zu verstehen.

Warum sollte ich das letzte Element abschneiden? In Python ist das letzte Element das zuletzt hinzugefügte Element, also das neueste. Dass will ich ganz sicher nicht abschneiden sondern auswerten. Ich will die Liste auch nicht verändern, sondern mit meinem Code unterschiedlich lange Listen auswerten können.

Bitte schau doch nocheinmal meine ursprüngliche Frage an, da steht auch ein Beispiel dafür welches Ergebnis ich haben will.

Inzwischen habe ich auch eine Lösung, trotzdem vielen Dank für deine Mühe.

0
jo135  16.02.2024, 21:20
@derkiesi
wenn ich die schleifenvariable i mit 1 multipliziere dann bleibt diese gleich i. Das führt also zu nichts.

Natürlich führt das zu etwas, nämlich zur korrekt funktionierenden Lösung. Probier's aus.

Warum sollte ich das letzte Element abschneiden?

Weil dann die Lösung sehr viel einfacher zu verstehen ist, ganz ohne Indexakrobatik. Das muss auch gar nicht die bestehende Liste tatsächlich verändern, wenn du dir eine separate Listenansicht als Slice anlegst und davon jeweils ein Stück "abschneidest". Ein Slice ist eben keine neue Liste.

0
derkiesi 
Fragesteller
 16.02.2024, 22:47
@jo135

hab ich gemacht.

Dieser Code:

liste = [18, 10, 1, 4, 17, 9, 6, 15, 13, 20]

# Slice-schleife, um die jeweils letzten x Elemente auszugeben

for i in range(3):

Tripple = liste[-3 * (i + 1):len(liste) - i * 3]

print(Tripple)

führt zu dieser Ausgabe:

[15, 13, 20]

[17, 9, 6]

[10, 1, 4]

und wenn ich 1 statt 3 einsetze:

liste = [18, 10, 1, 4, 17, 9, 6, 15, 13, 20]

# Slice-schleife, um die jeweils letzten x Elemente auszugeben

for i in range(3):

Tripple = liste[-1 * (i + 1):len(liste) - i * 1]

print(Tripple)

dann bekomme ich:

[20]

[13]

[15]

das ist beides nicht das gewünschte Ergebniss, siehe Frage.

0
jo135  17.02.2024, 07:58
@derkiesi
Tripple = liste[-1 * (i + 1):len(liste) - i * 1]

Natürlich funktioniert das so nicht, weil das fixe Intervall von 3 Elementen sein muss, damit es "Tripel" bleiben. Dass Interval und Iteration (beide 3) im Anfangsindex

Tripple = liste[-3 * (i + 1):len(liste) - i * 3]

zusammengefasst sind, ist simple Grundschulmathematik: -3*(i+1) = - 3*i - 3 . Dir geht es aber nur um die Iteration, also ist zu trennen:

for i in range(3):
  Tripple = liste[-i-3:len(liste)-i]
  print(Tripple)
0
derkiesi 
Fragesteller
 17.02.2024, 21:07
@jo135

Ich verstehe echt nicht was Du da schreibst. :-(

Macht aber nix, dein Code liefert mir eh nicht das gewünschte Ergebniss. :-)

hier das Ergebnis deines Codes:

[15, 13, 20]

[6, 15, 13]

[9, 6, 15]

Es ist auch egal, ich bin nun schon einige Schritte weiter und mit der Weiterverarbeitung meiner Ergebnisse beschäftigt.

0