Seite 1 von 1

sort() bei class, er macht was nur was? ;-)

Verfasst: Mittwoch 14. Februar 2007, 08:37
von nihilist
Hallo ich habe mir auch ein Programm geschrieben, das Filme in eine Textdatei einliest.
Nun möchte ich diese auch sortieren, erstmal nur nach dem Filmtitel

Code: Alles auswählen

choice = 0
weiter = True
import pickle as p
moviefile = 'simmsave'

class film:
    def __init__(self, name, year,lend):
        self.name = name
        self.year = year
        self.lend = lend
        print 'Film %s initialisiert' % self.name

    def info(self):
        print '"%s" "%s" "%s" ' %(self.name, self.year, self.lend)

try:
    f = file(moviefile)
    gl = p.load(f)

except:
    ab = []
    f = file(moviefile, 'w')
    p.dump(ab, f)
    f.close()

def menu ():
    print 'Bitte Auswahl treffen'
    print '                           (1) Um die komplette Liste anzuzeigen'
    print '                           (2) Um einen Film zu suchen'
    print '                           (3) Um einen neuen Film hinzuzufuegen'
    print '                           (4) Um einen Film zu loeschen'
    print '                           (5) Liste Sortieren'
    print '                           (6) Um zu speichern'
    print '                           (0) Beenden'


menu()
while True:
    choice = int(raw_input('Was wollen sie machen? '))
    if choice == 1:
        print 'Titel        Jahr       Verliehen an'
        if len(gl) > 0:
            for item in gl:
                item.info()
        else:
            print 'Noch nichts in die Liste eingetragen'

    elif choice == 2:
        searchitem = raw_input('Nach was suchen?: ')
        for titel in gl:
            if titel.lend == searchitem:
                titel.info()
                break
        else:
            print 'Name nicht gefunden'


    elif choice == 3:
        new_name = raw_input('Bitte Filmnamen eingeben: ')
        new_year = raw_input('Bitte Erscheinungsjahr eingeben: ')
        new_lend = raw_input('Verliehen?: ')
        new_name = film(new_name, new_year, new_lend)
        gl.append(new_name)

    elif choice == 4:
        deleteitem = raw_input('Welchen Film loeschen? ')
        for film in gl:
            if film.name == deleteitem:
                gl.remove(film)
                print 'Film geloescht'
                break
        else:
            print 'Kann Film nicht finden'
    elif choice == 6:
        f = file(moviefile, 'w')
        p.dump(gl, f)
        f.close()
        print 'Filmliste gespeichert'


    elif choice == 0:
        save = raw_input('Speichern vor dem Beenden?(j/n) ')
        if save == 'j':
            f = file(moviefile, 'w')
            p.dump(gl, f)
            f.close()
            print 'Liste gespeichert, Programm Beendet'
            break
        elif save == 'n':
            print 'Beendet ohne zu speichern'
            break

    elif choice == 5:
            gl.sort()
            print 'Sortiert'
Nun, was soll ich sagen, er sortiert, aber nach keinem Schema, zumindest keines das ich bisher durchschaut habe.
Habe vorher ein ähnliches Programm geschrieben das allerdings nur die Namen in eine Textdatei eingelesen hat, und da hats mit
gl.sort()
funktioniert.

Verfasst: Mittwoch 14. Februar 2007, 09:11
von Rebecca
Naja, du versuchtst, eine Liste von selbstgebauten Klasses zu vergleichen. Aber woher soll Python wissen, nach was fuer Kriterien du Objekte dieser Klasse sortieren willst? Um zu sortieren, musst du Python mitteilen, was es bedeuten soll, dass zwei film-Objekte gleich sind, und wann ein film-Objekt groesser/kleiner ist als ein anderes... Dafuer kannst du die Vergleichs-Operatoren der film-Klasse ueberschreiben, schau mal hier: http://docs.python.org/ref/customization.html

PS: Klassennamen schreibt man gross

Verfasst: Mittwoch 14. Februar 2007, 12:09
von nihilist
danke dir,
ich denke das dürfte dann mit
__comp__
gehen.

Hast du vielleicht dazu ein kleines Beispiel zur Hand? Ich tu mich (noch) schwer mit dem Anwenden auf mein Programm.


P.S.
Klassenname ist jetzt gross... ;-)

Verfasst: Mittwoch 14. Februar 2007, 12:13
von nkoehring
Mal ne allgemeine Zwischenfrage, wenn wir schonmal bei .sort() sind... was genau ist das eigentlich fuer ein Algorithmus hinter .sort()? Ich weiß nur das er schweineschnell ist ^^

Verfasst: Mittwoch 14. Februar 2007, 13:28
von Rebecca
Wenn man zum Beispiel eine Personenklasse nach dem name-Attribut sortiert haben will:

Code: Alles auswählen

#!/usr/bin/env python

class Person:

    def __init__(self, name, geburtstag):
            self.name = name;
            self.geburtstag = geburtstag

    def __cmp__(self, other):
        return cmp(self.name, other.name)

    def __str__(self):
        return "%s (%s)" % (self.name, self.geburtstag)


liste = [Person("Egon Meier", "1.1.1970"),
         Person("Maria Mueller", "7.7.1977"),
         Person("Otto Schmitt", "9.9.1959")]

liste.sort()

for entry in liste:
    print entry

Verfasst: Mittwoch 14. Februar 2007, 13:38
von birkenfeld
nkoehring hat geschrieben:Mal ne allgemeine Zwischenfrage, wenn wir schonmal bei .sort() sind... was genau ist das eigentlich fuer ein Algorithmus hinter .sort()? Ich weiß nur das er schweineschnell ist ^^
Das ist Timsort, benannt nach Tim Peters. Näheres nachzulesen gibts hier: http://svn.python.org/view/python/trunk ... &view=auto

Verfasst: Mittwoch 14. Februar 2007, 15:16
von nkoehring
birkenfeld hat geschrieben: Das ist Timsort, benannt nach Tim Peters. Näheres nachzulesen gibts hier: http://svn.python.org/view/python/trunk ... &view=auto
Ah vielen Dank... :) Ich hab irgendwie nie was bei meinen Recherchen entdecken koennen.

Verfasst: Mittwoch 14. Februar 2007, 20:07
von nihilist
@ Rebecca
Danke dir, das hat geklappt, gar nicht so schwer wenn mans mal weiß...;-)

Ist es auch möglich zwei __cmp__ einzubinden? Damit man die Liste je nach Laune auch nach anderen Kriterien sortieren kann?
Aber das kann ich ja auch einfach mal versuchen....

Verfasst: Mittwoch 14. Februar 2007, 20:35
von rayo
Hi

Da fallen mir gerade 2 Varianten ein:

Code: Alles auswählen

#1. Variante
import operator
liste.sort(key=operator.attrgetter('geburtstag'))

for entry in liste:
    print entry

#2. Variante
def cmp2(this, other):
    return cmp(this.geburtstag, other.geburtstag)
liste.sort(cmp=cmp2)

for entry in liste:
    print entry
Für beide Varianten bräuchtest du die __cmp__-Methode nicht mehr.

Bei der ersten kannst du mit operator.attrgetter ein Attribut nehmen um zu vergleichen.

Bei der zweiten Variante eine externe compare-Funktion, bei der auch komplexere Vergleiche gehen (zuerst nach Namen dann nach Geburtstag sortieren).

Gruss