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
kaytec
User
Beiträge: 608
Registriert: Dienstag 13. Februar 2007, 21:57

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: 569
Registriert: Samstag 8. April 2006, 12:31
Wohnort: Brandenburg

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

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: 569
Registriert: Samstag 8. April 2006, 12:31
Wohnort: Brandenburg

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

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: 569
Registriert: Samstag 8. April 2006, 12:31
Wohnort: Brandenburg

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: 608
Registriert: Dienstag 13. Februar 2007, 21:57

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: 569
Registriert: Samstag 8. April 2006, 12:31
Wohnort: Brandenburg

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: 608
Registriert: Dienstag 13. Februar 2007, 21:57

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: 569
Registriert: Samstag 8. April 2006, 12:31
Wohnort: Brandenburg

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 ...
Benutzeravatar
kaytec
User
Beiträge: 608
Registriert: Dienstag 13. Februar 2007, 21:57

Danke Michael !

Nein du hast es schon richtig verstanden. Ich wollte nur aufzeigen, daß es verschiedene Möglichkeiten gibt. Die Plätze stecken ja auch schon in der Liste ohne Zahlen, doch würde ich die Liste mit "print" für den Benutzer des Spieles ausgeben, dann müsste ich sie auch wieder in Zahlenform darstellen.

z.B.: Lina hat 3 mal den 1 Platz belegt

Dein code habe ich probiert und der ist auch schon super - ich werde ihn noch für meine Zwecke umbauen.

gruss und dank frank
Benutzeravatar
kaytec
User
Beiträge: 608
Registriert: Dienstag 13. Februar 2007, 21:57

Die Lösung von Michael hat zwar funktioniert, doch ich habe sie nicht verstanden. Jetzt habe ich eine eigene Lösung gefunden und hoffe sie ist auch soweit ok.

Code: Alles auswählen

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

plaetze_gesamt_wertung = list()
platz_einzel_wertung = list()
zaehler = 1
for name in namen:
    for einzel_wertung in gesamt_wertung:
        for spieler in einzel_wertung:
            if name == spieler:
                platz_einzel_wertung.append(zaehler)
            zaehler += 1
        zaehler = 1
    plaetze_gesamt_wertung.append(sorted(platz_einzel_wertung))
    platz_einzel_wertung = list()
        
for name, platz in sorted(zip(namen,plaetze_gesamt_wertung), key=lambda x: x[1]):
    print str(zaehler) + ' Platz fuer ' + name
    print '--> Plaetzen in den Einzelspielen ' + '|'.join(str(i) for i in platz)
    zaehler += 1
gruss frank
BlackJack

Ist von der Laufzeit nicht so besonders schön, und auch komplizierter als es sein müsste. Die äussere Schleife über die Namen kann man loswerden und den `zaehler` sollte man nicht selbst verwalten, sondern mit `enumerate()` erzeugen.

Was bei Deinen Lösungen oft das Verständnis erschwert ist, dass Du zusammengehörige Informationen oft auf verschiedene Listen aufteilst und sie nur durch den Index in den verschiedenen Listen "verbunden" sind.

Code: Alles auswählen

def main():
    gesamt_wertung = [['Frankie', 'Merkel', 'PG', 'Lina'],
                      ['Lina', 'Frankie', 'PG', 'Merkel'],
                      ['Merkel', 'Frankie', 'Lina', 'PG'],
                      ['Lina', 'Frankie', 'Merkel', 'PG']]
    # 
    # Abbildung von Namen auf eine Liste von Plätzen in den Einzelspielen.
    # 
    name2plaetze = dict()
    for wertung in gesamt_wertung:
        for platz, spieler in enumerate(wertung):
            name2plaetze.setdefault(spieler, list()).append(platz + 1)
    # 
    # Die Plätze der Einzelspiele sortieren.
    # 
    for plaetze in name2plaetze.itervalues():
        plaetze.sort()
    # 
    # Daraus eine sortierte Gesamtplazierung erstellen.  Die Eintraege
    # haben die Form ([<plaetze>,...], 'name').
    # 
    plaetze_sortiert = sorted((plaetze, name)
                              for name, plaetze in name2plaetze.iteritems())
    # 
    # Und ausgeben...
    # 
    for gesamt_platz, (plaetze, name) in enumerate(plaetze_sortiert):
        print '%3d Platz fuer %s' % (gesamt_platz + 1, name)
        print '--> Plaetze in den Einzelspielen', '|'.join(map(str, plaetze))
Benutzeravatar
kaytec
User
Beiträge: 608
Registriert: Dienstag 13. Februar 2007, 21:57

Danke BlackJack!

Habe mir es mal angeschaut - du erzeugst ja eigentlich genauso eine Liste wie ich.

Code: Alles auswählen

plaetze_sortiert = sorted((plaetze, name)
                          for name, plaetze in name2plaetze.iteritems())

sorted(zip(namen,plaetze_gesamt_wertung), key=lambda x: x[1])

Die "Namensliste" lasse ich mir übergeben und du erzeugst sie mit Hilfe einer dict()

Den zaehler ersetzt du mit enumerate() - dies zählt die Liste mit dem Startwert 0 durch !?

map() ersetzt die for-schleife !?

Das deine Version besser ist nehme ich mal an, doch warum ist mir nicht wirklich klar ?

gruss und dank frank
Antworten