Struct-QList nach bestimmter Variable des Structs sortieren

Alles rund um die Programmierung mit Qt
Antworten
Timebeast
Beiträge: 22
Registriert: 21. August 2007 21:48
Wohnort: Hann.-Münden

Struct-QList nach bestimmter Variable des Structs sortieren

Beitrag von Timebeast »

und noch ne Frage auf die ich keine Antwort finde,... :?

Ich hab mir ne QList gebastelt und zwar so:
struct TestStruct{
int x;
int y;
int z;
};
QList<TestStruct> TestList;

Dann schreibe ich halt integer in die Liste, jeweils halt x, y, z.
So wenn ich dann alle Daten in die Liste geschrieben hab will ich die Liste mit qSort nach dem Integer z sortieren.

Also im Prinzip:
qSort(TestList[0].z.begin(), TestList[0].z.end());

Tja geht nicht...auch:
qSort(TestList.begin(), TestList.end()); //<-- klar eigendlich, woher soll er wissen das er nach z sortieren soll
qSort(TestList.z.begin(), TestList.z.end()); //geht auch nicht, er sagt `class QList<ComPort::TestStruct>' has no member named `z'
qSort(TestList[].z.begin(), TestList[].z.end()); //Fehler:parse error before `]' token
qSort(TestList[0].z.begin(), TestList[4].z.end()); //"4" ist das Ende des Arrays bzw. der Liste, geht so aber auch nicht

Ich hoffe Ihr erkennt mein Problem... :(

Bis denn
Ralf
FaS
Beiträge: 184
Registriert: 25. Mai 2006 19:48
Kontaktdaten:

Beitrag von FaS »

Aus der Doku:

Code: Alles auswählen

void qSort ( RandomAccessIterator begin, RandomAccessIterator end, LessThan lessThan )
Für dein Problem kannst du dir also eine Funktion basteln, die 2 structs bekommt und wo du dann selbst entscheiden musst, welches kleiner ist, also indem der die z-Werte vergleicht:

Code: Alles auswählen

struct TestStruct
{
  TestStruct( int x_, int y_, int z_ );
  static bool lessThan( const TestStruct &ts1_, const TestStruct &ts2_ );
  int x;
  int y;
  int z;
};

TestStruct::TestStruct( int x_, int y_, int z_ )
: x( x_ ), y( y_ ), z( z_ ) // Initialisierungsliste
{
  // leer
}

bool TestStruct::lessThan( const TestStruct &ts1_, const TestStruct &ts2_ )
{
  return ts1_.z < ts2_.z;
}

// Beispiel:
QList<TestStruct> testList;
testList << TestStruct( 1, 2, 3 ) << TestStruct( 6, 4, 1 ) << TestStruct( 2, 8, 9 );
qSort( testList.begin(), testList.end(), TestStruct::lessThan );
PS: Die lessThan()-Funktion könnte natürlich auch außerhalb des structs deklariert/definiert werden

MfG,
FaS
Timebeast
Beiträge: 22
Registriert: 21. August 2007 21:48
Wohnort: Hann.-Münden

Beitrag von Timebeast »

Hallo FaS,

äääh, ja, so´n Workaround hab ich mir auch schon überlegt, aber nicht ganz so umständlich:

Code: Alles auswählen

int n(0);
int v(1);

while(TestList_End){                           //<--Pseudocode
      If (TestList[n].z<TestList[v].z){
           TestList.swap(n, v);
      }
      v++;
}
Er vergleicht halt den ersten Eintrag von TestList.z mit allen anderen und wenn ein kleinerer gefunden wurde stellt er ihn an den Anfang. Danach wird der Algorytmus halt mit dem zweiten Eintrag gestartet usw.

Aber das hat nichts mit meiner Frage zu tun!!! :oops:

Geht das nicht auch mit QSort???

Danke trotzdem FaS :wink:

Gruß Ralf
FaS
Beiträge: 184
Registriert: 25. Mai 2006 19:48
Kontaktdaten:

Beitrag von FaS »

und wenn ein kleinerer gefunden wurde stellt er ihn an den Anfang
Dein Algorithmus macht das Gegenteil, er sortiert von groß nach klein, nur falls du dich über deine Ausgaben wundern solltest... ;-)

-----

qSort benutzt halt einen heap sort Algorithmus und benötigt zum Vergleichen den kleiner-als-Operator auf dem Datentyp, der bei dir nicht existiert; wie du sagtest, woher soll er wissen, dass er den z-Wert vergleichen soll - das kann man dem aber beibringen (siehe unten), man könnte ihm auch Addition beibringen etc.

Meine vorgeschlagene Variante ist doch bloß um eine Vergleichsfunktion komplizierter als dein Versuch mit dem qSort, brauchst diese Funktion ja nichtmal in deim Strukt drin haben. qSort benutzt dann eben statt dem "<"-Zeichen die angegebene Funktion für alle erforderlichen Vergleiche. Falls du auch nach anderen Variablen sortieren willst, kannst du ja einfach mehrere Vergleichsfunktionen schreiben:

Code: Alles auswählen

bool testStructZLessThan( const TestStruct &ts1, const TestStruct &ts2 ) {
  return ts1.z < ts2.z;
}
qSort( testList.begin(), testList.end(), testStructZLessThan );
Eine bessere Möglichkeit gibt es nicht, außer du bringst deinem struct bei sich zu vergleichen:
Wenn dein Strukt/Klasse logisch kleiner als ein anderes ist, wenn man den z-Wert vergleicht, dann kannst du den "<"-Operator im struct definieren, so dass auch die direkte Variante von qSort damit klar kommt, denn dann hat er keine Probleme mehr direkt zwei structs miteinander zu vergleichen. Ist eigentlich dasselbe wie mit meiner zusätzlichen lessThan-Funktion, ein Operator ist ja quasi eine Funktion:

Code: Alles auswählen

struct TestStruct {
  int x;
  int y;
  int z;
  inline bool operator<( const TestStruct &c ) {
    return z < c.z;
  };
};

// funktioniert jetzt:
qSort( testList.begin(), testList.end() );
MfG,
FaS
Antworten