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.
audax
User
Beiträge: 830
Registriert: Mittwoch 19. Dezember 2007, 10:38

Alternative mit Addition:

Code: Alles auswählen

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

print list(transform(liste1, liste2))
The Peacemaker
User
Beiträge: 17
Registriert: Freitag 23. Mai 2008, 17:55

audax hat geschrieben: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))







setzt dieser ansatz dictonarys voraus?

ich habs mal auf meine listen angewandt, und ich erhalte leider "IndexError: list index out of range"




nachtrag:

muss es nicht "if idx == current[1]" heissen, wenn ich das 2. element bearbeiten will?

so bekomm ich nämnlich keinen indexfehler mehr.
audax
User
Beiträge: 830
Registriert: Mittwoch 19. Dezember 2007, 10:38

Zu deinem Nachtrag:
Nein, der Index liegt doch im ersten Teil des Paares.

Und jetzt zeig eben deine Listen her..meine Güte.
BlackJack

Irgendwie ist mir die Aufgabe immer noch nicht klar. Und ich dachte schon, ich hätte sie verstanden. Soll die zweite Liste also mit Elementen aus der ersten aufgefüllt werden? Ich dachte es sollten Elemente in der zweiten *aus* der zweiten in Lücken wiederholt werden.

Vielleicht ist es ein wenig ungünstig, dass die Beispieldaten in beiden Listen die gleichen Werte zu den jeweiligen Indexen haben, so sieht man nicht wo die Ergebnisse her kommen sollen.

Nehmen wir mal das hier als Beispiel:

Code: Alles auswählen

    a = [(0, 4.7), (1, 1.1), (2, 1.3), (3, 3.1), (4, 0.0)]
    b = [(1, 2.3), (3, 4.2)]
Wie müsste jetzt ein aufgefülltes `b` aussehen und wo kämen diese Werte jeweils her?

Edit: Und was kann man über die Indexe sagen? Sind die wirklich in der ersten Liste immer aufsteigend? So lückenlos? Ist der Startindex bekannt?
The Peacemaker
User
Beiträge: 17
Registriert: Freitag 23. Mai 2008, 17:55

hab eben festgestellt dass mit meiner liste typ 1 was nicht stimmt.




das wäre ein bsp für ne liste typ 2:
[(53, 0.45018192137800001), (128, 0.34728442829700001), (129, 0.456179211084), (235, 0.36925521471700001), (482, 0.49590614351599999), (594, 0.56499722755699999), (603, 0.77058100829599996), (617, 0.75543537563499996), (626, 0.53642891059599995), (652, 0.68153047985500004),.......


nachtrag: fehler in liste 1 behoben.


die sieht so aus:

[(0, 0.0), (1, 0.0), (2, 0.0), (3, 0.0), (4, 0.0), (5, 0.0), (6, 0.0), (7, 0.0), (8, 0.0), (9, 0.0), (10, 0.0), (11, 0.0), (12, 0.0), (13, 0.0), (14, 0.0), (15, 0.0), (16, 0.0), (17, 0.0), (18, 0.0),
(19, 0.0), (20, 0.0), (21, 0.017494697371800001), (22, 0.053225052132200003), (23, 0.053225052132200003), (24, 0.083480231271999994), (25, 0.14087127320199999), (26, 0.14087127320199999), (27, 0.14087127320199999), (28, 0.14087127320199999), (29, 0.14087127320199999), (30, 0.200210336756), (31, 0.25113326636299999), (32, 0.19374222443299999), (33, 0.16348704529300001), (34, 0.16348704529300001), (35, 0.21146625670800001), (36, 0.26542000342599997), (37, 0.26542000342599997), (38, 0.26542000342599997), (39, 0.21449707381899999), (40, 0.21449707381899999), (41, 0.21449707381899999),.....





nachtrag2:

nochmal ne ausführliche erklärung: :)

(2. wert des jeweiligen tupels der 1. liste) - (2. wert des jeweiligen tupels der 2. liste)

der 1. wert (also der index) jedes tupels soll nicht geändert werden.


wenn man auf eine lücke stösst in der 2. liste, soll der vorgängerwert für die subtraktion verwendet werden. der vorgängwerwert kann auch weiter hinten liegen, je nachdem wie gross die lücke ist.

wenn ich zB in der 1. liste bei (5, 0.5) bin, es in liste 2 aber leider nur ein (3, 0.3) und ein (6, 0.1) gibt, soll er (5, 0.5) - (3, 0.3) = (5, 0.2) rechnen und das ergebis an eine neue liste anhängen.

ich hoffe es wurde einigermassen klar :)


nachtrag3:


ich glaube das größte problem ist, dass nicht immer ein erstes element in der 2. liste vorhanden ist. dann greift er quasi ins "leere"

da sollte er dann mit einer 0 rechnen.

ich werkel mal weiter, wenn sich was tut melde ich mich.
bin weiterhin für vorschläge dankbar.
BlackJack

Noch immer nicht ganz. Liste 2 fängt mit einer Lücke an, dass heisst es gibt keinen Vorgängerwert. Und nochmal die Frage: Welche garantierten Eigenschaften haben die Indexe in Liste 1? So wie das im Beispiel aussieht, ist das einfach nur der Index des Tupels in der Liste, also völlig überflüssige und redundante Information. Wenn dem so ist, bräuchte man die Liste nicht einmal anschauen um die fehlenden Werte in der zweiten zu "erfinden". Wenn die Frage mit dem Startwert für die erse Lücke geklärt wäre…
The Peacemaker
User
Beiträge: 17
Registriert: Freitag 23. Mai 2008, 17:55

BlackJack hat geschrieben:Noch immer nicht ganz. Liste 2 fängt mit einer Lücke an, dass heisst es gibt keinen Vorgängerwert. Und nochmal die Frage: Welche garantierten Eigenschaften haben die Indexe in Liste 1? So wie das im Beispiel aussieht, ist das einfach nur der Index des Tupels in der Liste, also völlig überflüssige und redundante Information. Wenn dem so ist, bräuchte man die Liste nicht einmal anschauen um die fehlenden Werte in der zweiten zu "erfinden". Wenn die Frage mit dem Startwert für die erse Lücke geklärt wäre…

Liste 2 KANN mit einer Lücke anfangen, muss aber nicht.


die indexe von liste 1 fangen bei 0 an und steigen dann einfach auf, je nachdem wie lang die liste ist die icheinlese. es gibt aber keine sprünge drin.

in der liste, in der nachher die ergebisse landen, sollten die indexe wieder drin sein, die brauch ich später bei der auswertung der ergebnisse.



ich mal euch mal ein bild:


Liste1: [(0,0), (1, 0.5), (2, 0.1 ), (3, 0.4), (4, 0.2 ), (5, 0.6)]
Liste 2: [ (1, 0,1), (5, 0.1)]
Liste mit Ergebnis: [(0,0), (1, 0.4), (2, 0), (3, 0.3), (4, 0.1), (5, 0.5)]
Lonestar
User
Beiträge: 147
Registriert: Samstag 9. August 2008, 08:31

die Startbedingung mit der 2. Liste machts irgendwie wesentlich komplizierter als es vorher war, aber nu kommt eine auf die schnelle zusammengeferkelte Variante die zumindest das problem mit deinem Beispiellisten nach deinen Anforderungen löst:

Code: Alles auswählen

a = [(0,0), (1, 0.5), (2, 0.1 ), (3, 0.4), (4, 0.2 ), (5, 0.6)] 
b = [ (1, 0.1), (5, 0.1)] 
c = []

def sub_list(a,b):
    print a[1], " - ", b[1]
    return (a[1] - b[1])

def comp_index(a,b):
    if a[0] == b[0]: 
        return True
    return False
    
    
j = 0
for i in xrange(len(a)):
    if j == 0:
        if comp_index( a[i], b[j]):
            c.append((i, sub_list(a[i], b[j])))
            j +=1
        else:    
            c.append((i, a[i][1]))
            if comp_index( a[i], b[j]):
                j +=1
    else:
        c.append((i, sub_list(a[i], b[j])))
        if  comp_index( a[i], b[j]):
            j +=1
print c
Wäre Liste 2 mit nem ordenltichen Startwert Versehen - in deinem Beispiel (0,0) könnte der ganze Rönz unter 'if j == 0:' wegfallen. Ich lass mich mal überraschen wie man das in ordentlichem Python löst

[edit]
aber mal was anderes - wozu brauchst du überhaupt den Index in dem Tupel? Wenn der Index immer mit dem Listenplatz übereinstimmt ist das doch wie BlackJack schon sagt redundant und eigentlich nicht mehr nötig.
[/edit]
The Peacemaker
User
Beiträge: 17
Registriert: Freitag 23. Mai 2008, 17:55

Lonestar hat geschrieben:
[edit]
aber mal was anderes - wozu brauchst du überhaupt den Index in dem Tupel? Wenn der Index immer mit dem Listenplatz übereinstimmt ist das doch wie BlackJack schon sagt redundant und eigentlich nicht mehr nötig.
[/edit]

naja... bei liste 2 hätte ich ja sonst nur zahlen aneinander gereiht. wie soll ich die dann dem entsprechenden wert aus liste 1 zuordnen?
BlackJack

@The Peacemaker: Und *noch einmal* die Frage: Was soll bei Lücken vor dem ersten Wert passieren? Es kann doch nicht so schwer sein diese Frage mal zu beantworten!? Wo kommt die (0,0) in Deinem Ergebnis her? Also insbesondere der zweite Wert. Sollen die Werte vor dem ersten Index einfach mit 0en versehen werden, oder braucht man dafür irgendwie die erste Liste?

Das gezeigte Ergebnis bekommt man jedenfalls so:

Code: Alles auswählen

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


def fill_gaps(data):
    last_index, last_value = (0, 0.0)
    for index, value in data:
        for dummy in xrange(last_index, index):
            yield last_value
        yield value
        last_index, last_value = index + 1, value


isecond = partial(imap, itemgetter(1))


def main():
    data_a = [(0, 0.0), (1, 0.5), (2, 0.1), (3, 0.4), (4, 0.2), (5, 0.6)]
    data_b = [(1, 0.1), (5, 0.1)]
    
    result = list(enumerate(imap(sub, isecond(data_a), fill_gaps(data_b))))
    print result
@Lonestar: Die beiden Funktionen sind etwas übertrieben, sogar in C wären sie das. Insbesondere `comp_index()` was eigentlich auch nur ein Einzeiler wäre:

Code: Alles auswählen

def comp_index(a, b):
    return a[0] == b[0]
BlackJack

@The Peacemaker: Aber in der *ersten* Liste sind die Indexe in den Tupeln einfach nur überflüssig. In meiner letzten Lösung entferne ich die vorher und füge sie hinterher wieder hinzu. Ist also nur zusätzliche Arbeit.
The Peacemaker
User
Beiträge: 17
Registriert: Freitag 23. Mai 2008, 17:55

BlackJack hat geschrieben:@The Peacemaker: Und *noch einmal* die Frage: Was soll bei Lücken vor dem ersten Wert passieren? Es kann doch nicht so schwer sein diese Frage mal zu beantworten!? Wo kommt die (0,0) in Deinem Ergebnis her? Also insbesondere der zweite Wert. Sollen die Werte vor dem ersten Index einfach mit 0en versehen werden, oder braucht man dafür irgendwie die erste Liste?

tut mir leid, das hab ich wohl beim editieren gelöscht.

ich dachte mir dass er da einfach ne 0 reinschreiben soll. das ist auch nicht so schlimm, da die ergebnisse erst interessant werden wenn sich in liste2 was tut.



eure ergebnisse funktionieren gut, vielen dank erstmal dafür. ich hab nur noch das problem dass eine meiner listen für liste2 "IndexError: list index out of range" produziert, ich bin noch dabei herauszufinden wieso.
Lonestar
User
Beiträge: 147
Registriert: Samstag 9. August 2008, 08:31

BlackJack hat geschrieben:
@Lonestar: Die beiden Funktionen sind etwas übertrieben, sogar in C wären sie das. Insbesondere `comp_index()` was eigentlich auch nur ein Einzeiler wäre:
ja, das die Funktionen hier übertrieben sind ist mir nu aber auch aufgefallen. Allerdings habe ich mir angewöhnt sobald ich eine Redundanz bei Berechnungen habe diese direkt in eine externe Funktion auszulagern. Sowas wurde bei mir einfach viel zu oft unglaublich unübersichtlich - und wenn ich mich dann mal entschliessen konnte etwas auszulagern hab ich schon öfters selber nicht mehr auf Anhieb ganz durchgeblickt...
So habe ich zwar ab und an einige Funktionen die man sich sparen könnte - aber es wird dadurch halt nicht wirklich schlechter lesbar.

Allerdings werde ich mich heute Abend mal bei Gelegenheit hinsetzen und mir mit Verstand ansehen wie es in python auch in schön geht - vor allem enumerate und map könnten mir das Leben glaube ich wesentlich erleichtern
abgdf

@Lonestar: Natürlich hätte ich auch mit der xrange()-Schleife gearbeitet, wenn es mehr als 2 Listen gewesen wären.

@audax: Natürlich verwende ich in Python auch Module, wenn es der einfachste Weg ist.
Dein Code ist auch doof. Ich hol' gleich meinen großen Bruder, und der wirft mit Sand.

@The Peacemaker: Erst wenn Dir klar ist, was Du ausdrücken willst, kann man das in Code umsetzen.

Gruß
yipyip
User
Beiträge: 418
Registriert: Samstag 12. Juli 2008, 01:18

Falls noch jemand daran interessiert ist (und ich das Problem richtig verstanden habe), hier meine Loesung:

Code: Alles auswählen

def sub_lists(ls1, ls2):

  default = 0
  idx = 0
  
  for x1, y1 in ls1:
    x2, y2 = ls2[idx]
    if x1 == x2:
      default = y2
      idx += 1

    yield x1, y1 - default


ls1 = [(0, 1), (1, 0.5), (2, 0.1 ), (3, 0.4), (4, 0.2 ), (5, 0.6)]
ls2 = [(1, 0.1), (5, 0.1)]

print list(sub_lists(ls1, ls2))
:wink:
yipyip
The Peacemaker
User
Beiträge: 17
Registriert: Freitag 23. Mai 2008, 17:55

also eure lösungen sind alle super, bin euch sehr dankbar!



ich hab nur eine interessante beobachtung gemacht.


bei manchen listen bekomm ich:

Traceback (most recent call last):
File "C:\Studienarbeit\Modul3.py", line 242, in <module>
print list(sub_lists(ls1, ls2))
File "C:\Studienarbeit\Modul3.py", line 223, in sub_lists
x2, y2 = ls2[idx]
IndexError: list index out of range



der fehler tritt z.B. dann auf wenn in der 2. liste das letzt element (x, 0.0) ist.


hat jmd von euch ne erklärung dafür?

kann es damit zusammenhängen dass die listen sehr lang sind? wenn ich z.B. die liste ls2 = [(1, 0.1), (5, 0.1)] nehm, und als erste liste nehm ich eine mit ca. 10000 einträgen, kommt die meldung auch.

:?
BlackJack

Ja da gibt's 'ne ganz einfache Erklärung für. Und die solltest Du wirklich selber heraus finden und es hat auch nichts mit besonders langen Listen zu tun. Wenn Du den Quelltext nicht in soweit nachverfolgen kannst um das Problem zu sehen, solltest Du vielleicht keine Studienarbeit mit einer Programmiersprache in Angriff nehmen.

Mach Dir klar was die Fehlermeldung bedeutet, wie die bei der gezeigten Zeile auftreten kann, und wie es dazu kommt.
yipyip
User
Beiträge: 418
Registriert: Samstag 12. Juli 2008, 01:18

Sorry, schwerer, logischer Index-Fehler meinerseits:
Schon bei

Code: Alles auswählen

ls1 = [(0, 1), (1, 0.5), (2, 0.1 ), (3, 0.4), (4, 0.2 ), (5, 0.6)]
ls2 = [(0, 1)]
ist 'idx' nach dem ersten Durchlauf gleich 1, erzeugt beim naechsten Schleifendurchlauf also
den Index-Error.

So aber:

Code: Alles auswählen

def sub_lists(ls1, ls2):

  default = 0
  idx = 0

  max_idx = len(ls2) - 1
  for x1, y1 in ls1:
    x2, y2 = ls2[idx]
    if x1 == x2:
      default = y2
      idx = min(max_idx, idx + 1)

    yield x1, y1 - default
Sieht jetzt ein bisschen wie ein Workaround aus, halte ich bei der Aufgabenstellung aber trotzdem nicht fuer das Allerschlechteste.
:oops: :wink:
yipyip
Zuletzt geändert von yipyip am Donnerstag 4. September 2008, 21:43, insgesamt 1-mal geändert.
yipyip
User
Beiträge: 418
Registriert: Samstag 12. Juli 2008, 01:18

ups, BlackJack war schon da...
The Peacemaker
User
Beiträge: 17
Registriert: Freitag 23. Mai 2008, 17:55

Ich bin Programmieranfänger, und habe mir in letzter Zeit extrem viel selbst beigebracht. Aber wie ihr euch denken könnt fängt man nicht gleich als Profi an, und da denke ich nicht dass es falsch ist mal nachzufragen, wenn man mal selbst nicht weiterkommt. Ausserdem ist das nur ein winziger Teil des Programms, und der Hauptaspekt der Arbeit liegt ohnehin in der Evaluierung der Ergebnisse.




Mein Programm tut jetzt wunderbar, hab noch einige Sachen angeglichen.

Hätte noch ne letzte Frage:

Wie kann ich jetzt die 2. Elemente der Tupel auslesen und in eine neue Liste schreiben?

Mit Strings hab ichs schon vor einigen Tagen hinbekommen, da konnte ich die ersten Elemente problemlos löschen, aber mit den Floats will das nicht so ganz.
Antworten