Sortieren von zwei Listen nach gleichen Sotiermechanismus ?

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.
Benutzeravatar
Michael Schneider
User
Beiträge: 566
Registriert: Samstag 8. April 2006, 12:31
Wohnort: Bremen
Kontaktdaten:

Beitragvon Michael Schneider » Sonntag 17. Juni 2007, 07:44

Hallo Frank!
kaytec hat geschrieben:Das mit zip() habe ich so halbwegs verstanden, doch ich vertsehe nicht was die lambdafunktion macht !

"lambda x: -x[0]" definiert eine Funktion, die als Argument x (entspricht dann einem (Punkte, Name)-Paar) erhält, von dem es das erste Element extrahiert und negiert zurückgibt. Das wird vor dem Sortieren auf alle Elemente der (Punkte, Name)-Paarliste angewendet, so dass intern eine Liste von negativen Punktwerten erzeugt wird. Negativ deshalb, weil 'sorted' standardmäßig aufwärts sortiert und somit die betragsmäßig größten Werte nach oben sortiert werden. Ich hoffe, ich habe das richtig verstanden, denn dafür gibt ja noch das Attribute 'reverse' [EDIT: Argument, sorry]:
2.1 Built-in Functions hat geschrieben:sorted( iterable[, cmp[, key[, reverse]]])


kaytec hat geschrieben:Sinn bei meinen Sortierproblem würde für mich machen, wenn die keys der einen liste an die anderen gebunden wären. Verändere ich die eine liste, dann verändert sich die andere - ohne die Anbindung von Bedingungen. :oops: - hat das jemand verstanden ?

In Python gibt es für zusammengehörige Werte den Datentyp Tupel, der die zusammengehörigen Werte zu einer Einheit zusammenfasst. Die Lösungsvorschläge beruhen darauf, dass die zusammen gehörenden Namen und Werte zu einer Liste von Paaren zusammengefasst, dann sortiert und dann wieder getrennt werden.

Grüße,
Michael
Zuletzt geändert von Michael Schneider am Sonntag 17. Juni 2007, 15:56, insgesamt 1-mal geändert.
Diese Nachricht zersört sich in 5 Sekunden selbst ...
Benutzeravatar
Michael Schneider
User
Beiträge: 566
Registriert: Samstag 8. April 2006, 12:31
Wohnort: Bremen
Kontaktdaten:

Beitragvon Michael Schneider » Sonntag 17. Juni 2007, 12:48

Hi Frank,

wie wäre es mit diesem Vorschlag als Erweiterung des bisher Gesagten:

Code: Alles auswählen

def reverse_parallel_sort(*sequences):
    i = iter(xrange(len(sequences[0])))
    return zip(*sorted(zip(*sequences), key=lambda t: (t[0], -i.next()), reverse=True))

def parallel_sort(*sequences):
    i = iter(xrange(len(sequences[0])))
    return zip(*sorted(zip(*sequences), key=lambda t: (t[0], i.next())))

p = [17, 13, 16, 17]
n = ["Heinz", "Depp", "Merkel", "PG"]
print reverse_parallel_sort(p, n)
print parallel_sort(p, n)


>>> [(17, 17, 16, 13), ('Heinz', 'PG', 'Merkel', 'Depp')]
>>> [(13, 16, 17, 17), ('Depp', 'Merkel', 'Heinz', 'PG')]

Zur Erklärung:
i = iter(xrange(...)) erzeugt ein Objekt, das bei jedem Aufruf seiner next()-Methode einen weiteren Zähler aus dem Bereich [0..len-1] berechnet und zurückgibt.
Das Hauptkonstrukt ist größtenteils gleich, nur dass die Schlüsselfunktion ein Tupel aus (Punktzahl, Rang) zurückgibt, wobei der Rang schrittweise hochgezählt wird (bzw. runter, wenn danach rückwärts sortiert wird). Bei gleicher Punktezahl wird also der Rang in der Liste berücksichtigt. Die letztgenannten Tupel werden nur für den Sortieralgorithmus erzeugt und beeinflussen nicht die (Punktzahl, Name)-Paare. Außerdem wird die Sortierorientierung über das sorted()-Attribut reverse gesteuert.

Mit diesen Funktionen kannst Du nun beliebige Sequenzen parallel so wie die Erste sortieren - aufwärts mit parallel_sort(...) und abwärts mit reverse_parallel_sort(...). Dabei sind die Ergebnislisten immer genau so lang wie die kürzeste Eingangsliste!

Grüße,
Michael
Diese Nachricht zersört sich in 5 Sekunden selbst ...
BlackJack

Beitragvon BlackJack » Sonntag 17. Juni 2007, 13:09

Wozu ist `i` gut?
Benutzeravatar
Michael Schneider
User
Beiträge: 566
Registriert: Samstag 8. April 2006, 12:31
Wohnort: Bremen
Kontaktdaten:

Beitragvon Michael Schneider » Sonntag 17. Juni 2007, 13:28

Hi BlackJack,

i soll den Iterator speichern, der bei jedem Aufruf durch sorted hochgezählt wird. Das Problem ist, dass ich ein Objekt benötige, das innerhalb von sorted hochgezählt wird, nicht außerhalb. Hätte auch einen eigenen Generator wie

Code: Alles auswählen

i = (x for x in range(len(sequences[0])))

schreiben können, was aber nicht viel schöner ist. Es gibt sicher noch viele andere Möglichkeiten, das ist nur die, die mir spontan einfiel. Ich bin für alles offen. :-)

Grüße,
Michael
Diese Nachricht zersört sich in 5 Sekunden selbst ...
BlackJack

Beitragvon BlackJack » Sonntag 17. Juni 2007, 13:53

Was das `i` *ist* habe ich ich schon verstanden, ich wollte wissen wozu man das hier braucht!?
Benutzeravatar
kaytec
User
Beiträge: 513
Registriert: Dienstag 13. Februar 2007, 21:57

Beitragvon kaytec » Sonntag 17. Juni 2007, 14:44

Hallo und Dank an alle Beteiligten!

Die Version von birkenfeld ist schon richtig. Hatte noch einen alten reverse() drin und so hatte es natürlich nicht richtig funktioniert :oops:

So - nun habe ich ja viel zu lesen und mache mal Hausaufgaben.

danke frank
Benutzeravatar
Michael Schneider
User
Beiträge: 566
Registriert: Samstag 8. April 2006, 12:31
Wohnort: Bremen
Kontaktdaten:

Beitragvon Michael Schneider » Sonntag 17. Juni 2007, 16:13

Hallo Blacky!
BlackJack hat geschrieben:Was das `i` *ist* habe ich ich schon verstanden, ich wollte wissen wozu man das hier braucht!?

Man benötigt den Namen, um auf das Objekt zuzugreifen. (wer blöd fragt, bekommt blöde antworten)
Das war jetzt nicht unhöflich gemeint. Ich habe ausführlich formuliert, was i ist und warum (das Problem) ich es einsetzte. Bevor ich weiter rate, was Du eigentlich von mir wissen möchtest, bist Du dran zu erklären, was Du meinst.

Wenn Deine eigentliche Frage war, warum ich einen extra Iterator einbaue, obwohl das auch so funktioniert, dann ist die Antwort, dass ich von kaytecs Information überrascht war, es würde nicht funktionieren. So zweifelte ich daran, dass Python die Reihenfolge immer beibehält und wollte eine wirklich sichere Variante anbieten.

Grüße,
Michael
Diese Nachricht zersört sich in 5 Sekunden selbst ...
BlackJack

Beitragvon BlackJack » Sonntag 17. Juni 2007, 16:37

Meine eigentliche Frage war genau letztere. Python's Sortiermethode ist "stable". Jedenfalls ab Python 2.3. Du solltest wirklich mal upgraden. :-)
Benutzeravatar
Michael Schneider
User
Beiträge: 566
Registriert: Samstag 8. April 2006, 12:31
Wohnort: Bremen
Kontaktdaten:

Beitragvon Michael Schneider » Sonntag 17. Juni 2007, 17:55

BlackJack hat geschrieben:Meine eigentliche Frage war genau letztere. Python's Sortiermethode ist "stable". Jedenfalls ab Python 2.3. Du solltest wirklich mal upgraden. :-)

Ich nutze privat 2.4.1 :-)
Dass "stable" genau das ausdrückt, wusste ich nicht. Meine Lösung finde ich also mindestens genauso gut wie überflüssig. :wink:

Grüße,
Michael
Diese Nachricht zersört sich in 5 Sekunden selbst ...
Benutzeravatar
birkenfeld
Python-Forum Veteran
Beiträge: 1603
Registriert: Montag 20. März 2006, 15:29
Wohnort: Die aufstrebende Universitätsstadt bei München

Beitragvon birkenfeld » Sonntag 17. Juni 2007, 20:13

Michael Schneider hat geschrieben:Hätte auch einen eigenen Generator wie

Code: Alles auswählen

i = (x for x in range(len(sequences[0])))

schreiben können, was aber nicht viel schöner ist. Es gibt sicher noch viele andere Möglichkeiten, das ist nur die, die mir spontan einfiel. Ich bin für alles offen. :-)


Code: Alles auswählen

itertools.count()


Huch, gibts erst ab 2.3.
Dann lieber noch Vim 7 als Windows 7.

http://pythonic.pocoo.org/
Benutzeravatar
Michael Schneider
User
Beiträge: 566
Registriert: Samstag 8. April 2006, 12:31
Wohnort: Bremen
Kontaktdaten:

Beitragvon Michael Schneider » Sonntag 17. Juni 2007, 20:57

Hi Birkenfeld!
birkenfeld hat geschrieben:

Code: Alles auswählen

itertools.count()


Huch, gibts erst ab 2.3.

Soll das eine Anspielung sein? :lol:

Michel

ps. Ich hatte gerade einen kleinen Roman für Stony geschrieben und konnte ihn nicht mehr absetzen, weil Du den Thread geschlossen hast. :-(
Diese Nachricht zersört sich in 5 Sekunden selbst ...
Benutzeravatar
kaytec
User
Beiträge: 513
Registriert: Dienstag 13. Februar 2007, 21:57

Beitragvon kaytec » Freitag 22. Juni 2007, 19:43

Habe nun das nächste Problem und komme nicht wirklich auf eine Lösung.

Code: Alles auswählen

gesamt_wertung = [[('Gabi', 1), ('Tux', 2), ('Frankie', 3), ('Schroeder', 4)],
                  [('Schroeder', 1), ('Frankie', 2), ('Tux', 3), ('Gabi', 4)],
                  [('Tux', 1), ('Gabi', 2), ('Frankie', 3), ('Schroeder', 4)],
                  [('Tux', 1), ('Frankie', 2), ('Gabi', 3), ('Schroeder', 4)]]

gesamt_wertung = [(['Svetlana', 'Merkel', 'Bush', 'Bloedel'], [1, 2, 3, 4]),
                  (['Bloedel', 'Svetlana', 'Bush', 'Merkel'], [1, 2, 3, 4]),
                  (['Merkel', 'Svetlana', 'Bloedel', 'Bush'], [1, 2, 3, 4]),
                  (['Bloedel', 'Merkel', 'Bush', 'Svetlana'], [1, 2, 3, 4])]

gesamt_werung = [['Frankie', 'Merkel', 'PG', 'Lina'],
                 ['Lina', 'Frankie', 'PG', 'Merkel'],
                 ['Merkel', 'Frankie', 'Lina', 'PG'],
                 ['Lina', 'Frankie', 'Merkel', 'PG']]


Mit den oben gezeigten Möglichkeiten kann ich mir die Gesamtwertung aus einem Würfelspiel übergeben lassen. Diese möchte ich nun auswerten und nach der Anzahl der Plätze bzw. "Bestplatzierten " ausgeben. Ich bekomme aber nicht eine sinvolle Sortierung bzw. Umwandlung hin!?

gruss und dank frank
Benutzeravatar
Michael Schneider
User
Beiträge: 566
Registriert: Samstag 8. April 2006, 12:31
Wohnort: Bremen
Kontaktdaten:

Beitragvon Michael Schneider » Freitag 22. Juni 2007, 22:28

Hi Frank!

kaytec hat geschrieben:Mit den oben gezeigten Möglichkeiten kann ich mir die Gesamtwertung aus einem Würfelspiel übergeben lassen. Diese möchte ich nun auswerten und nach der Anzahl der Plätze bzw. "Bestplatzierten " ausgeben. Ich bekomme aber nicht eine sinvolle Sortierung bzw. Umwandlung hin!?

Sag uns doch erstmal, was Deine Kriterien für einen "Bestplatzierten" sind. Wer die wenigsten Plätze hat (also die kleinste Summe aller Plätze), oder wer das beste Mittel hat?
So könnte eine Auswertung nach bestem Mittel aussehn:

Code: Alles auswählen

gesamt_wertung = [['Frankie', 'Merkel', 'PG', 'Lina'],
                 ['Lina', 'Frankie', 'PG', 'Merkel'],
                 ['Merkel', 'Frankie', 'Lina', 'PG'],
                 ['Lina', 'Frankie', 'Merkel', 'PG']]

lSpieler = gesamt_wertung[0]
dWertung = dict([(sSpieler, []) for sSpieler in lSpieler])

for lGame in gesamt_wertung:
    for sSpieler in lSpieler:
        dWertung[sSpieler].append(lGame.index(sSpieler) + 1)
       
lWertung = sorted([(lPlaetze, sName) for sName, lPlaetze in dWertung.items()],
                  key=lambda (lPlaetze, sName): (sum(lPlaetze), sName))
for iRang, (lPlaetze, sName) in enumerate(lWertung):
    print "%i. Rang: %s mit Plaetzen %s"%(iRang+1, sName, ", ".join(map(str, sorted(lPlaetze))))

Aber am besten Du beschreibst erstmal genau, was Du suchst.

Grüße,
der Michel
Diese Nachricht zersört sich in 5 Sekunden selbst ...
Benutzeravatar
kaytec
User
Beiträge: 513
Registriert: Dienstag 13. Februar 2007, 21:57

Beitragvon kaytec » Freitag 22. Juni 2007, 22:45

das mit einer Dictonary habe ich mir auch schon gedacht, da ich die Namen ersetzen könnte und nur die Plätze auswerte - ok - erst mal die Fragen beantworten:

Die Listen stehen in richtiger Reihenfolge - Der Gewinner ist immer am Anfang und die Plätze zählen nach Platz in der Liste. Bei diesem Beispiel sind 4 Spiele gamacht worden. Die Bindung an den Platz [ 1, 2, 3, 4] ist eigentlich nicht relevant, doch für die Auswertung evt. einfacher, denn so habe ich z.B. bei zip() schon die Bindung an die Plätze und muß diese nicht erst so sortieren. Meine Frage ist : Ich möchte eine sinnvolle Sortierung erzeugen, um eine verwertbare list() dict() etc. zu haben, die ich dann ausgeben kann.

Es sind im oberen Beispiel drei Möglichkeiten gegeben, die ich erzeugen könnte. Für die Umsetzung im Spiel verwende ich natürlich nur eine.

Doppelnamen sind eigentlich nicht erwünscht und werden später noch verhindert.

gruss und dank frank
Benutzeravatar
Michael Schneider
User
Beiträge: 566
Registriert: Samstag 8. April 2006, 12:31
Wohnort: Bremen
Kontaktdaten:

Beitragvon Michael Schneider » Samstag 23. Juni 2007, 10:51

Hi Frank!

kaytec hat geschrieben:Die Listen stehen in richtiger Reihenfolge - Der Gewinner ist immer am Anfang und die Plätze zählen nach Platz in der Liste. Bei diesem Beispiel sind 4 Spiele gamacht worden. Die Bindung an den Platz [ 1, 2, 3, 4] ist eigentlich nicht relevant, doch für die Auswertung evt. einfacher, denn so habe ich z.B. bei zip() schon die Bindung an die Plätze und muß diese nicht erst so sortieren. Meine Frage ist : Ich möchte eine sinnvolle Sortierung erzeugen, um eine verwertbare list() dict() etc. zu haben, die ich dann ausgeben kann.

Entweder war es gestern zu spät und heute ist es einfach noch zu früh für mich, oder kapiere das einfach nicht. :-(
Was meinst Du mit Deinem letzten Satz? Möchtest Du eine "verwertbare" Liste, oder eine die Du ausgeben kannst? Meiner Erfahrung nach wiederspricht sich das in aller Regel. :-)
Was ich eigentlich wissen wollte, war, wie Du den Rang eines Spielers über alle Spiele ermittelst. Ob Du, wie in meinem Beispiel, alle Einzelplätze aufsummierst und dann die kleinste Zahl ermittelst - dann hätte Frankie gewonnen.
Du kannst aber auch prüfen, wer am oftesten auf Platz 1 landete, bei Gleichstand wer von diesen am oftesten auf Platz 2 landete usw. - dann hätte Lina gewonnen.

Vielleicht verkenne ich auch den Sinn Deiner Frage und Du willst Deine drei Listen nicht verarbeiten, sondern erhalten! Sei nachsichtig mit mir, ich bin manchmal einfach blind. 8)

Grüße,
der Michel
Diese Nachricht zersört sich in 5 Sekunden selbst ...

Wer ist online?

Mitglieder in diesem Forum: Google [Bot]