`map`-Funktion auf `set()` mit Tupeln anwenden

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
Atalanttore
User
Beiträge: 407
Registriert: Freitag 6. August 2010, 17:03

Hallo

Die Koordinaten (x, y, z) in einem `set()` mit Tupeln würde ich gerne mit der `map`-Funktion abändern. Auf jede Achse soll eine andere Funktion angewendet werden.

Bei meinem unten erstellten Beispielcode kommt folgende Fehlermeldung:

Code: Alles auswählen

Traceback (most recent call last):
  File "/home/ata/source/move-coordinates.py", line 20, in <module>
    result_x = map(add_30, i[0])
TypeError: 'int' object is not iterable
Was habe ich falsch gemacht?

Code:

Code: Alles auswählen

coordinates = {(34, 45, 435), (78, 67, 76), (45, 35, 98), (56, 86, 68), (32, 46, 86)}
results = set()


def add_30(n):
    return n + 30


def add_20(n):
    return n + 20


def add_10(n):
    return n + 10


for i in coordinates:
    result_x = map(add_30, i[0])
    result_y = map(add_20, i[1])
    result_z = map(add_10, i[2])

    results.add((result_x, result_y, result_z))

print(results)
Gruß
Atalanttore
Benutzeravatar
sparrow
User
Beiträge: 4538
Registriert: Freitag 17. April 2009, 10:28

Warum nutzt du keine list comprehension?
Oder übersehe ich hier etwas beim erwarteten Resultat?

Code: Alles auswählen

>>> coordinates
{(32, 46, 86), (45, 35, 98), (56, 86, 68), (78, 67, 76), (34, 45, 435)}
>>> [(e[0]+30, e[1]+20, e[2]+10) for e in coordinates]
[(62, 66, 96), (75, 55, 108), (86, 106, 78), (108, 87, 86), (64, 65, 445)]
>>>
Benutzeravatar
snafu
User
Beiträge: 6866
Registriert: Donnerstag 21. Februar 2008, 17:31
Wohnort: Gelsenkirchen

Du hast anscheinend map() noch nicht richtig verstanden. Du iterierst bei deinem Beispiel über alle Tupel und nimmst davon via i[0] das jeweils erste Element. Dies ist eine Zahl und damit kann map() nichts anfangen, weil es etwas iterierbares erwartet, z.B. eine Liste oder ein Tupel. Aber selbst wenn du nur i übergeben würdest, käme nicht heraus, was du erwartest. Du suchst wohl eher etwas in dieser Art:

Code: Alles auswählen

print([(x + 10, y + 20, z + 30) for x, y, z in coordinates])
Oder eben direkt als Set:

Code: Alles auswählen

set((x + 10, y + 20, z + 30) for x, y, z in coordinates)
Man kann in Python, wie du siehst, die Schleife zum Transformieren der Daten und die Erzeugung des neuen Containers unmittelbar als Einzeiler verknüpfen.
Benutzeravatar
snafu
User
Beiträge: 6866
Registriert: Donnerstag 21. Februar 2008, 17:31
Wohnort: Gelsenkirchen

@Atalanttore: Wenn du viel mit Zahlen und Berechnungen machst, dann schau dir auch mal die wissenschaftlichen Pakete für Python an, die man zusätzlich installieren kann. Ein populäres davon ist pandas. Das kann Daten auch aus externen Quellen, z.B. einer CSV-Datei, beziehen. Zum Verändern der Koordinaten kann man dann sogar die Schleife weglassen:

Code: Alles auswählen

In [11]: df = pd.DataFrame({(34, 45, 435), (78, 67, 76), (45, 35, 98), (56, 86, 68), (32, 46, 86)})

In [12]: df
Out[12]:
    0   1    2
0  32  46   86
1  45  35   98
2  56  86   68
3  78  67   76
4  34  45  435

In [13]: df + (10, 20, 30)
Out[13]:
    0    1    2
0  42   66  116
1  55   55  128
2  66  106   98
3  88   87  106
4  44   65  465
Benutzeravatar
__blackjack__
User
Beiträge: 14044
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

Ich würde hier auch eine comprehension schreiben, es sei denn man hat bereits eine passende Funktion die man anwenden kann. Nur um das mit `map()` mal gesehen zu haben:

Code: Alles auswählen

In [7]: set(map(lambda p: (p[0] + 30, p[1] + 20, p[2] + 10), coordinates))
Out[7]: {(62, 66, 96), (64, 65, 445), (75, 55, 108), (86, 106, 78), (108, 87, 86)}
„A life is like a garden. Perfect moments can be had, but not preserved, except in memory. LLAP” — Leonard Nimoy's last tweet.
Atalanttore
User
Beiträge: 407
Registriert: Freitag 6. August 2010, 17:03

sparrow hat geschrieben: Donnerstag 30. Mai 2019, 20:50 Warum nutzt du keine list comprehension?
Oder übersehe ich hier etwas beim erwarteten Resultat?
snafu hat geschrieben: Donnerstag 30. Mai 2019, 20:54 Du iterierst bei deinem Beispiel über alle Tupel und nimmst davon via i[0] das jeweils erste Element. Dies ist eine Zahl und damit kann map() nichts anfangen, weil es etwas iterierbares erwartet, z.B. eine Liste oder ein Tupel. Aber selbst wenn du nur i übergeben würdest, käme nicht heraus, was du erwartest. Du suchst wohl eher etwas in dieser Art:

Code: Alles auswählen

print([(x + 10, y + 20, z + 30) for x, y, z in coordinates])
Oder eben direkt als Set:

Code: Alles auswählen

set((x + 10, y + 20, z + 30) for x, y, z in coordinates)
Man kann in Python, wie du siehst, die Schleife zum Transformieren der Daten und die Erzeugung des neuen Containers unmittelbar als Einzeiler verknüpfen.
__blackjack__ hat geschrieben: Donnerstag 30. Mai 2019, 23:18 Ich würde hier auch eine comprehension schreiben, es sei denn man hat bereits eine passende Funktion die man anwenden kann. Nur um das mit `map()` mal gesehen zu haben:

Code: Alles auswählen

In [7]: set(map(lambda p: (p[0] + 30, p[1] + 20, p[2] + 10), coordinates))
Out[7]: {(62, 66, 96), (64, 65, 445), (75, 55, 108), (86, 106, 78), (108, 87, 86)}
Danke für die vielen Erläuterungen. Eine Comprehension führt zum gewünschten Ergebnis. Die Variante mit `map()` und `lambda`-Funktion sieht auch komplizierter aus.

`map()` habe ich noch nie gebraucht. Ist `map()` nur für die Anwendung von längeren Funktionen, die für eine Comprehension zu lange sind, gedacht?

snafu hat geschrieben: Donnerstag 30. Mai 2019, 20:54 Du hast anscheinend map() noch nicht richtig verstanden.
Ich vermute, dass ich vieles an Python noch gar nicht kenne. :wink:

snafu hat geschrieben: Donnerstag 30. Mai 2019, 21:32 @Atalanttore: Wenn du viel mit Zahlen und Berechnungen machst, dann schau dir auch mal die wissenschaftlichen Pakete für Python an, die man zusätzlich installieren kann. Ein populäres davon ist pandas. Das kann Daten auch aus externen Quellen, z.B. einer CSV-Datei, beziehen. Zum Verändern der Koordinaten kann man dann sogar die Schleife weglassen:

Code: Alles auswählen

In [11]: df = pd.DataFrame({(34, 45, 435), (78, 67, 76), (45, 35, 98), (56, 86, 68), (32, 46, 86)})
Danke für den Hinweis.

Gruß
Atalanttore
Benutzeravatar
__blackjack__
User
Beiträge: 14044
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

@Atalanttore: `map()` ist ein typisches funktionales Werkzeug. Die Funktion ist praktisch wenn man ein „iterable“ und eine Funktion/Methode hat, und die auf jedes Element anwenden will und ein damit ein neues „iterable“ mit den Ergebnissen bekommt. Beispiele wäre das parsen einer Zeile mit Koordinaten: ``x, y, z = map(int, line.split(','))``. Oder wenn man eine Liste mit Objekten hat, deren Zeichenkettenrepresentation man durch ein Zeichen getrennt dargestellt haben möchte: ``', '.join(map(str, items))``.
„A life is like a garden. Perfect moments can be had, but not preserved, except in memory. LLAP” — Leonard Nimoy's last tweet.
Atalanttore
User
Beiträge: 407
Registriert: Freitag 6. August 2010, 17:03

@__blackjack__: Danke für die Erklärung.

Gruß
Atalanttore
Antworten