liste mit 2er tupel subtrahieren

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.
The Peacemaker
User
Beiträge: 17
Registriert: Freitag 23. Mai 2008, 17:55

hab mal wieder ein kleines problem :?


ich hab jetzt 2 listen, die 2-er tupel enthalten.

jetzt will ich die 2. werte in den tupeln jeweils voneinander abziehen. das ergebnis soll dann in eine neue liste.

leider hab ich noch keine möglichkeit gefunden wie ich die werte subtrahieren kann :roll:


wäre nett wenn mir jmd einen tipp geben könnte. :D
EyDu
User
Beiträge: 4881
Registriert: Donnerstag 20. Juli 2006, 23:06
Wohnort: Berlin

Code: Alles auswählen

l3 = map(lambda ((a,b), (x,y)): b-y, zip(l1, l2))
?
Zuletzt geändert von EyDu am Donnerstag 4. September 2008, 07:34, insgesamt 1-mal geändert.
The Peacemaker
User
Beiträge: 17
Registriert: Freitag 23. Mai 2008, 17:55

leider will das nicht so wie ich will :(


ich möchte eben durch beide listen gleichzeitig itterieren, und dabei soll bei jedem schritt jeweils das 2. element der 2. liste vom 2. element der 1. liste abgezogen werden. die jeweiligen ergebnisse sollen dnan an eine neue liste angehängt werden. ich werkel schon den ganzen abend dran rum, leider ohne erfolg.
audax
User
Beiträge: 830
Registriert: Mittwoch 19. Dezember 2007, 10:38

Großer Tip:
Erstelle neue Listen mit dem jeweils zweiten Element der ersten Listen und arbeite damit weiter.
The Peacemaker
User
Beiträge: 17
Registriert: Freitag 23. Mai 2008, 17:55

guter punkt, werd ich in erwägung ziehen.
BlackJack

Code: Alles auswählen

from functools import partial
from itertools import imap
from operator import itemgetter, sub


def main():
    list_a = [(0, 10), (1, 20)]
    list_b = [(0, 5), (1, 10)]
    iter_second = partial(imap, itemgetter(1))
    print map(sub, iter_second(list_a), iter_second(list_b))
audax
User
Beiträge: 830
Registriert: Mittwoch 19. Dezember 2007, 10:38

Wie ich es gesagt habe ;)
abgdf

Hallo,

also, ich denke, da muß man weder mit lambda hantieren, noch aus 3 Modulen importieren:

Code: Alles auswählen

a = [(0, 10), (1, 20)]
b = [(0, 5), (1, 10)]

c = []

c.append(a[0][1] - b[0][1])
c.append(a[1][1] - b[1][1])

for i in c:
    print i
Oder verstehe ich da was falsch ?

Gruß
BlackJack

Lesbarkeit und Skalierbarkeit?

So ein doppelter Indexzugriff ist nicht so verständlich als wenn man den objekten vernünftige Namen gibt. Das haben wir bei den Beispielen nicht gemacht, weil wir nicht wissen was die Daten bedeuten, aber der Peacemaker weiss das ja.

Und wie sähe Dein Quelltext aus, wenn da 100 Tupel in jeder Liste sind, oder gar eine unbekannte Anzahl? Eine Schleife sollte mindestens sein.
audax
User
Beiträge: 830
Registriert: Mittwoch 19. Dezember 2007, 10:38

abgdf hat geschrieben:Hallo,

also, ich denke, da muß man weder mit lambda hantieren, noch aus 3 Modulen importieren:
Dein Code ist doof.

Hier mal die Variante ohne Importe (was absoluter Schwachsinn ist, denn was ist schon eine Sprache, wenn man die Module nicht nutzt?)

Code: Alles auswählen

a = [(0, 10), (1, 20)]
b = [(0, 5), (1, 10)]

a_, b_ = [y for x, y in lst
    (for lst in [a,b])]
c = [x+y for x, y in zip(a_, b_)]

print ', '.join(c)
Allerdings sollte man itertools.izip nehmen, das evaluiert `lazy`
Lonestar
User
Beiträge: 147
Registriert: Samstag 9. August 2008, 08:31

audax hat geschrieben: Dein Code ist doof.

Hier mal die Variante ohne Importe (was absoluter Schwachsinn ist, denn was ist schon eine Sprache, wenn man die Module nicht nutzt?)
Ob es nu sinnvoll ist oder nicht das Problem ohne andere Module zu lösen- da möchte ich mich mal raushalten. Mich interessiert viel mehr warum du deine Variante so aufbaust - ich wollte dein Beispiel gerade mal nachvollziehen bekomme es bei mir nicht zum laufen...

ich hätte aber auch mal ne kurze variante ohne Importe anzubieten

Code: Alles auswählen

a = [(0, 10), (1, 20)]
b = [(0, 5), (1, 10)]
c = []
 
for i in xrange(len(a)):
    c.append(a[i][1] - b[i][1])
    
print c
BlackJack

@Lonestar: Ein Grund so eine doppelte Indexierung zu vermeiden ist, dass es nur mit Sequenzen funktioniert während EyDu's, audax' und meine Varianten mit beliebigen "iterables" arbeiten, also flexibler sind. Ausserdem ist es sehr einfach unsere Lösungen so zu ändern, dass keine Liste sondern wieder ein "lazy iterable" als Ergebnis heraus kommt (`map()` → `imap()` bzw. Generatorausdruck statt "list comprehension").

Ich finde audax' Lösung nicht so toll und relativ unverständlich, was wohl daran liegt, dass er sich eben künstlich eingeschränkt hat, indem er keine Module importiert.
audax
User
Beiträge: 830
Registriert: Mittwoch 19. Dezember 2007, 10:38

Lonestar hat geschrieben: Ob es nu sinnvoll ist oder nicht das Problem ohne andere Module zu lösen- da möchte ich mich mal raushalten. Mich interessiert viel mehr warum du deine Variante so aufbaust - ich wollte dein Beispiel gerade mal nachvollziehen bekomme es bei mir nicht zum laufen...
So muss er lauten:

Code: Alles auswählen

a = [(0, 10), (1, 20)]
b = [(0, 5), (1, 10)]

a_ = [y for x, y in a]
b_ = [y for x, y in b]

c = [x-y for x, y in zip(a_, b_)]

print ', '.join(str(n) for n in c)
Was ich aber doof finde.

Und willst du wirklich ohne Module arbeiten? Dann zeig mir doch mal, wie du dann auch Kommandozeilen-Argumente zugreift oder Dateien löscht, etc...
Eine Sprache ist doch nur ein Gerüst für ihre Bibliothek!

So hätte ich es übrigens wirklich gelöst:

Code: Alles auswählen

second = partial(imap, op.itemgetter(1))
c = [a-b for a, b in izip(second(a), second(b))]

print ', '.join(imap(str, c))
Wobei mich da auch op.sub angelächelt hat ;)
The Peacemaker
User
Beiträge: 17
Registriert: Freitag 23. Mai 2008, 17:55

so ich werd mal ein bisschen präziser :)

also was ich genau will ist folgendes:

ich hab 2 liste mit 2er tupel.

die erste liste enthält als erstes element durchgehende indices und als zweites element float-werte.

die zweite liste ist genauso aufgebaut, enthält aber nur einen teil von der ersten liste.

bsp.:

liste1 = [(0, 0),(1, 0.5),(2,0.9),(3, 0.3),(4, 0.2),(5, 0.2),(6, 0.1)]
liste2 = [(1, 0.5),(3, 0.3),(5, 0.2),(6, 0.1)]



letztendlich will ist folgendes:

ich vergleiche beide listen miteinander, und wenn der index identisch ist, ziehe ich beide werte voneinander ab, und speichere die differenz in einer neuen liste, mit dem entsprechenden index.

findet man eine lücke in liste2, wird wieder subtrahiert, allerdings dann die letzte stelle wo man noch einen wert gefunden hat in liste2 vom aktuellen wert aus liste1.

bin schon wieder fleissig am rumtesten, aber ich bekomm immer "list index out of range" und "list indices must be integers" :(
Lonestar
User
Beiträge: 147
Registriert: Samstag 9. August 2008, 08:31

@BlackJack
ja das mit der doppelten Indexierung war mir schon klar das das nicht unbeding die schönste Lösung ist. Ich tue mich immer noch ein wenig schwer mit dem Iterieren in Python. Bei mir sitzt die C- Syntax so tief drin das ich fast immer wieder bei einer Schleife lande die irgendwie ein

Code: Alles auswählen

for i in xrange(len(liste)):
beinhaltet. Das ist auch mit der Hauptgrund warum ich regelmäßig hier bei den Fragen reinschaue und versuche nachzuvollziehen wie man es in Python besser/anders machen kann.

Deine Variante nachzuvollziehen hat mich auch ordentlich Zeit gekostet - wenn ich es aber richtig verstanden habe machst du es nicht viel anders als ich, nur das du durch 'imap' das durchlaufen meiner Schleife erledigen lässt. 'itemgetter(1)' verstehe ich momentan noch als das Äquivalent zu meinem 'a[1]'. Allerdings ist meine Lösung wie du schon sagtest nur direkt auf das gestellte Problem anwendbar - was ja zum Glück wenigstens nicht ganz falsch ist :wink:

und... @audax
ich weiss echt nicht was du willst? Zitierst mich noch und fragst trotzdem wie ich ohne Module arbeiten will? Ich schreibe es noch einmal für dich:

Ob es nu sinnvoll ist oder nicht das Problem ohne andere Module zu lösen- da möchte ich mich mal raushalten

... aber sorry nu werd ich hier ein wenig offtopic also
:arrow: back to topic

[edit]
zu langsam geschrieben - nu ist meine 0815 variante nicht mehr auf das Problem anwendbar...
[/edit]
audax
User
Beiträge: 830
Registriert: Mittwoch 19. Dezember 2007, 10:38

The Peacemaker hat geschrieben:so ich werd mal ein bisschen präziser :)

also was ich genau will ist folgendes:

ich hab 2 liste mit 2er tupel.

die erste liste enthält als erstes element durchgehende indices und als zweites element float-werte.

die zweite liste ist genauso aufgebaut, enthält aber nur einen teil von der ersten liste.

bsp.:

liste1 = [(0, 0),(1, 0.5),(2,0.9),(3, 0.3),(4, 0.2),(5, 0.2),(6, 0.1)]
liste2 = [(1, 0.5),(3, 0.3),(5, 0.2),(6, 0.1)]



letztendlich will ist folgendes:

ich vergleiche beide listen miteinander, und wenn der index identisch ist, ziehe ich beide werte voneinander ab, und speichere die differenz in einer neuen liste, mit dem entsprechenden index.

findet man eine lücke in liste2, wird wieder subtrahiert, allerdings dann die letzte stelle wo man noch einen wert gefunden hat in liste2 vom aktuellen wert aus liste1.

bin schon wieder fleissig am rumtesten, aber ich bekomm immer "list index out of range" und "list indices must be integers" :(
Uhm...mach einfach mal ein Vorher/Nachher Beispiel.

Ein Tip Vorweg: Dictionary sollten helfen.
BlackJack

@The Peacemaker: Ich würde mich audax anschliessen: Bitte Beispiele, denn die Erklärung reicht auch für mich nicht aus.

Ich interpretiere es bisher so, dass Du ein Ergebnis haben möchstest, das sozusagen `liste2` mit Werten auffüllt indem Tupel wiederholt werden, für die es keinen Index in `liste1` gibt. Also ungefähr so:

Code: Alles auswählen

liste1 = [(0, 0.0), (1, 0.5), (2, 0.9), (3, 0.3), (4, 0.2), (5, 0.2), (6, 0.1)]
liste2 = [(0, 0.0), (1, 0.5), (1, 0.5), (3, 0.3), (3, 0.3), (5, 0.2), (6, 0.1)]
#         ???????              ^^^^^^              ^^^^^^
Die eingefügten Elemenete sind im Kommentar gekennzeichnet, beim ersten weiss ich nicht welche Werte da rein sollen.
Lonestar
User
Beiträge: 147
Registriert: Samstag 9. August 2008, 08:31

ohne nun jemanden ärgern zu wollen - meine 0815 Variante mit der einfachen Schleife ist da auch 'noch' möglich. Allerdings sieht man sofort was ich damit meine das ich immer noch in C-Syntax denke...

Das von BlackJack angesprochene Problem mit dem 1. dic in Liste1 (0,0) habe ich mal aussen vor gelassen

Code: Alles auswählen

a =  [(0, 0),(1, 0.5),(2,0.9),(3, 0.3),(4, 0.2),(5, 0.2),(6, 0.1)] 
b =  [(1, 0.5),(3, 0.3),(5, 0.2),(6, 0.1)] 
c = []
 
j = 0
for i in xrange(len(a)):
    c.append((i,a[i][1] - b[j][1]))
    if  a[i][0] == b[j][0]:
        j +=1
        
print c
ich versuche das gerade mal spasseshalber mit der Variante von BlackJack aber anscheinend habe ich die doch nicht so gut verstanden wie ich dachte...
The Peacemaker
User
Beiträge: 17
Registriert: Freitag 23. Mai 2008, 17:55

BlackJack hat geschrieben:@The Peacemaker: Ich würde mich audax anschliessen: Bitte Beispiele, denn die Erklärung reicht auch für mich nicht aus.

Ich interpretiere es bisher so, dass Du ein Ergebnis haben möchstest, das sozusagen `liste2` mit Werten auffüllt indem Tupel wiederholt werden, für die es keinen Index in `liste1` gibt. Also ungefähr so:

Code: Alles auswählen

liste1 = [(0, 0.0), (1, 0.5), (2, 0.9), (3, 0.3), (4, 0.2), (5, 0.2), (6, 0.1)]
liste2 = [(0, 0.0), (1, 0.5), (1, 0.5), (3, 0.3), (3, 0.3), (5, 0.2), (6, 0.1)]
#         ???????              ^^^^^^              ^^^^^^
Die eingefügten Elemenete sind im Kommentar gekennzeichnet, beim ersten weiss ich nicht welche Werte da rein sollen.

du hast das genau richtig verstanden :)



meint ihr es ist sinnvoller die 2. liste aufzufüllen, und dann erst die berechnung durchzuführen? drauf bin ich nämlich noch garnicht gekommen. ich hätte eher immer aufs vorgängerelement zugegriffen.
audax
User
Beiträge: 830
Registriert: Mittwoch 19. Dezember 2007, 10:38

Also...so?

Code: Alles auswählen

liste1 = [(0, 0),(1, 0.5),(2,0.9),(3, 0.3),(4, 0.2),(5, 0.2),(6, 0.1)]
liste2 = [(1, 0.5),(3, 0.3),(5, 0.2),(6, 0.1)]


def transform(a, b):    
    j = 0
    for idx, val in a:
        current = b[j]
        if idx == current[0]:
            j += 1
            yield current
        yield idx, val

print list(transform(liste1, liste2))
Antworten