enums vergleichen



  • Hi,

    darf ich enums vergleichen? Falls nein, darf ich das, wenn ich explizit Werte zuweise:

    enum
    {
        APFEL = 1,
        BIRNE = 2
    };
    
    bool x = APFEL < BIRNE;
    

    ?

    Dritte Frage: Falls ich das auch nicht darf, wie löst ihr das dann? Ein set erscheint mir dann eigentlich recht sinnvoll, oder?



  • Eisflamme schrieb:

    darf ich enums vergleichen?

    Falls du Objekte von enum s meinst: Ja.

    Eisflamme schrieb:

    Dritte Frage: Falls ich das auch nicht darf, wie löst ihr das dann? Ein set erscheint mir dann eigentlich recht sinnvoll, oder?

    Falls du enum -Objekte nicht vergleichen dürftest, könnte das ein std::set auch nicht 😉

    Wobei, bei Zeigern ist es ja genau so. operator< ist für irgendwelche zwei Zeiger verboten, aber std::less ist erlaubt.



  • enum test1{
    	test11 = 1,
    	test12 = 2
    };
    enum test2{
    	test21 = 1,
    	test22 = 2
    };
    
    if(test1::test11 == test2::test21)
    		std::cout << "yes";
    	else
    		std::cout << "no";
    	if(test1::test11 == test2::test22)
    		std::cout << "yes";
    	else
    		std::cout << "no";
            if(test1::test11 == test2::test21)
    		std::cout << "yes";
    	else
    		std::cout << "no";
    

    Ergebnis:

    yes
    yes
    no
    

    Von daher, ja es geht 😉



  • Joscha__ schrieb:

    Von daher, ja es geht 😉

    Das beweist gar nichts! Der Compiler (den du nicht mal angegeben hast) könnte auch Fehlerhaft sein. Und statt dem ganzen "yes" und so hätte man die bool'schen Resultate ausgegeben und davor das Flag std::boolalpha gesetzt.



  • Dass man zwei unterschiedliche enums vergleichen kann, ist aber nicht sehr typsicher, das würde ich unterlassen.

    Achso und mit Vergleichen meine ich jetzt den operator<.

    Konkret:
    Ich habe Karten (Spielkarten wie in Poker, Skat etc.) und möchte jetzt gerne einen String von "Ks" umwandeln. K entspricht dabei KING (einem enum-Wert) und "s" der suit, also s wäre hier spade.

    Jetzt will ich zwei enum-Objekte vergleichen, also:

    enum Value
    {
        ACE,
        KING,
        //...
    };
    
    Value x = ACE, y = KING;
    bool comp = x < y;
    


  • Das hätte ich jetzt mit einer std::map gemacht, dann hast du den Namen der Karte (den du sicher irgendwann brauchst) auch dabei.



  • Okay, aber der Vergleich ist bei einer Map ja noch nicht direkt dabei oder würdest Du vergleichbare Objekte machen? Ich kombiniere nämlich gerade enum mit nem char.

    charValueMap.insert(CharValueMapType('2', TWO));
    				charValueMap.insert(CharValueMapType('3', THREE));
    				charValueMap.insert(CharValueMapType('4', FOUR));
    				charValueMap.insert(CharValueMapType('5', FIVE));
    				charValueMap.insert(CharValueMapType('6', SIX));
    				charValueMap.insert(CharValueMapType('7', SEVEN));
    				charValueMap.insert(CharValueMapType('8', EIGHT));
    				charValueMap.insert(CharValueMapType('9', NINE));
    				charValueMap.insert(CharValueMapType('T', TEN));
    				charValueMap.insert(CharValueMapType('t', TEN));
    				charValueMap.insert(CharValueMapType('J', JACK));
    				charValueMap.insert(CharValueMapType('j', JACK));
    				charValueMap.insert(CharValueMapType('Q', QUEEN));
    				charValueMap.insert(CharValueMapType('q', QUEEN));
    				charValueMap.insert(CharValueMapType('K', KING));
    				charValueMap.insert(CharValueMapType('k', KING));
    				charValueMap.insert(CharValueMapType('A', ACE));
    				charValueMap.insert(CharValueMapType('a', ACE));
    

    Denn A ist ja als char kleiner als K, was mir nicht passt.



  • Brauchst du wirklich eine std::map oder eher ein std::set mit std::pair<value, char> ?

    Du könntest jedenfalls einen eigenen Vergleichsfunktor angeben. Wobei das bei std::pair gar nicht nötig ist, dann wird einfach nach dem ersten ( first ) und bei Gleichheit nach dem zweiten ( second ) Member verglichen. Wenn der first -Member gerade dem Kartenwert entspricht und die Enumeratoren nach Wert sortiert sind, sollte das gerade dem gewünschten Verhalten entsprechen.



  • Den Vergleichsoperator zu benutzen fände ich okay, jedoch ist meiner Meinung nach ein Vergleich à la "Apfel ist kleiner als Birne" ein wenig komisch 😃
    Aber wie es aussieht willst du das bei einem Kartenspiel benutzen, da ginge es noch.



  • Hm, ich bin jetzt sogar auf eine bimap umgestiegen, weil ich anhand des Zeichens das enum-Objekt (für die Eingabe), aber auch umgekehrt (für die Ausgabe) haben möchte. Bei einem set wäre die Suche nicht für beide Richtungen optimiert, oder? Wenn ich nach second suchen würde, müsste ich ja linear durchgehen. Andererseits habe ich für die chars ja keine wirkliche Sortierung, sodass das sowieso linear ist, hm...



  • Für so wenige mögliche Werte könntest du locker in beiden Richtungen eine lineare Suche haben. Die logarithmische Laufzeitkomplexität zahlt sich vor allem bei grossen Containern aus.

    Von daher: Nimm die Lösung, die für dich am einfachsten und komfortabelsten ist.



  • Eisflamme schrieb:

    Hm, ich bin jetzt sogar auf eine bimap umgestiegen,

    Während der Rechnungen willst Du keine bimap, der op< muß performant sein, also einfach den enum in der Reihenfolge anlegen, die der op< vorgibt.
    Für die Ausgabe reicht es, den enum als Arrayindex zu nehmen. Vielleicht sogar für die GUI-Eingabe. Für die Konsolen- und Datei-Eingabe kannste irgendwas nehmen, std::strchr, std::string::find, std::find auf diversen Containern oder rohem Array oder String-Literal, std::map, std::hash_map, perfect hashing, auch ein 256 großen Array um von char zurückzukommen. Aber egal, die Eingabe dauert so unglaublich viele Millionen mal länger als so ein Nachkuckerchen, daß man da irgend eine naheliegende Lösung sucht.



  • Ok, bimap war irgendwie übertrieben. Aber ich merke gerade, dass der Flaschenhals bei mir sowieso wo anders liegt.

    Ich arbeite ja jetzt an einem Equity-Berechner, d.h. ich habe zwei Pokerblätter (5 Karten) und vergleiche diese. Wenn ich jetzt wie in Texas Hold'em aber nur die zwei Holecards habe, kommen noch fünf weitere Karten in die Mitte. Jetzt muss ich also 48*47*46*45*44 Kombinationen durchgehen und für jede prüfen, welche Hand besser ist. Mehr noch: Für jede dieser Kombinationen kann ich ja jeweils eine Holecard, zwei oder keine nutzen, d.h. ich muss 3x3 = 9 Kombinationen vergleichen.

    Das sind aber über eine Billion und meine Abfrage ist nicht wirklich performant genug, um das abzudecken. Wie kriege ich das denn schnell hin, gibt es da wohl irgend einen Trick?


Anmelden zum Antworten