Zeichenfolge in eine Liste speichern.

Wenn du dir nicht sicher bist, in welchem der anderen Foren du die Frage stellen sollst, dann bist du hier im Forum für allgemeine Fragen sicher richtig.
Antworten
thomasro0109
User
Beiträge: 5
Registriert: Mittwoch 22. Februar 2023, 14:05

Hallo Community,
ich habe eine Zeichenfolge und möchte nur die Zahlen in einer Liste speichern.

69|21||70|21||69|22||70|22||

oder auch mal

13|14||14|14|| oder 6|8||

Das Ganze sind dann X und Y Koordinaten.

Wie kann ich das machen?

Danke für Anregungen.

Thomas
__deets__
User
Beiträge: 14545
Registriert: Mittwoch 14. Oktober 2015, 14:29

Das ist ein sehr seltsames Format. *Muss* das so sein, oder hast du darueber Kontrolle? Denn ein sehr einfaches Rezept saehe so aus;

Code: Alles auswählen

import csv


def main():
    coordinates = [
        [(1, 2), (3, 4)],
        [(5, 6), (7, 8)],
    ]
    with open("/tmp/test.csv", "w", encoding="utf-8") as outf:
        writer = csv.writer(outf, delimiter="|")
        for row in coordinates:
            writer.writerow(f"{x}, {y}" for x, y in row)


# main guard
if __name__ == '__main__':
    main()
Sirius3
User
Beiträge: 18274
Registriert: Sonntag 21. Oktober 2012, 17:20

@__deets__: eine csv-Datei, in der eine Zelle mehrere Werte enthält ("1, 2") ist auch ein seltsames Format.

@thomasro0109: was hast Du Dir schon überlegt? Wo kommst Du nicht weiter? Welche Methoden gibt es, mit denen man Strings in Listen konvertieren kann?
__deets__
User
Beiträge: 14545
Registriert: Mittwoch 14. Oktober 2015, 14:29

@Sirus3: kann sein, muss nicht. Bei einer fixen Anzahl von Koordinaten pro zeile, ja. Da regelt man das ueber Spaltennamen. Wenn nicht (und das ist aus dem Ursprungspost wenn eher so ableitbar), finde ich es klarer so. Natuerlich ist das dann auch eine Dehnung des Begriffs CSV, aber ich sehe auch keinen Gewinn, das csv-Modul *nicht* zu nutzen.
Benutzeravatar
noisefloor
User
Beiträge: 4195
Registriert: Mittwoch 17. Oktober 2007, 21:40
Wohnort: WW
Kontaktdaten:

Hallo,

in _eine_ Liste, ohne Sublisten oder Tupel? Dann:

Code: Alles auswählen

>>> data = ' 69|21||70|21||69|22||70|22||'
>>> data = data.replace('||', '|')
>>> data_as_list = [item for item in data.split('|') if item]
>>> data_as_list
[' 69', '21', '70', '21', '69', '22', '70', '22']
>>>
Erscheint aber eher wenig sinnvoll, aus Koordinatenpaaren eine flache, 1-dimensionale Liste zu machen.

Gruß, noisefloor
Benutzeravatar
snafu
User
Beiträge: 6872
Registriert: Donnerstag 21. Februar 2008, 17:31
Wohnort: Gelsenkirchen

Code: Alles auswählen

def parse(data):
    return [
        tuple(map(int, coord.split("|")))
        for coord in data.split("||") if coord
    ]

def main():
    data = "69|21||70|21||69|22||70|22||"
    print(parse(data))

if __name__ == "__main__":
    main()
thomasro0109
User
Beiträge: 5
Registriert: Mittwoch 22. Februar 2023, 14:05

Hallo,
@__deets__
die Quelle der Daten ist leider nicht zu ändern. Muss so übernommen werden.

Ich habe das Programm von @snafu getestet und das funktioniert einwandfrei.

Vielen Dank für die Hilfe.
Thomas
Benutzeravatar
snafu
User
Beiträge: 6872
Registriert: Donnerstag 21. Februar 2008, 17:31
Wohnort: Gelsenkirchen

Wenn man keine Angst vor regulären Ausdrücken hat, könnte man das alternativ auch so schreiben:

Code: Alles auswählen

import re

COORDS_PATTERN = re.compile(r"(\d+)\|(\d+)(?=||)")

def get_coords(string):
    return [
        (int(x), int(y)) for x, y in COORDS_PATTERN.findall(string)
    ]

def main():
    data = "69|21||70|21||69|22||70|22||"
    print(get_coords(data))

if __name__ == "__main__":
    main()
Hierbei wird das vorgegebene Format noch etwas expliziter erfasst. Liest sich halt nur weniger schön und lässt keinen Spielraum für mögliche Leerzeichen innerhalb der Daten. Je nach Anwendungsfall kann das gut oder schlecht sein. Wenn es ein strikter Validierer sein soll, der überprüft ob der Datenstring gültig ist, dann würde ich es mit dem regulären Ausdruck schreiben, andernfalls mit den gezeigten String-Methoden.
Antworten