Sortierung std::vector

BOND_WR

Mitglied
Hallo,

ich habe einen vector der ein Objekt beinhaltet was folgende Eigenschaften hat:

Name, Datum, Zeit

ich möchten diesen vector nun nach 2 Kriterien sortieren:

1. Name (Doppelte Namen werden Gruppiert) und 2. Datum / Zeit

Beispiel vor Sortierung:

ABC 01.12.2007 12:00
AB 12.12.2007 12:00
ABC 13.12.2007 12:00

Beispiel nach Sortierung (so soll es aussehen):

ABC 13.12.2007 12:00 1. Gruppe mit Sortierung innerhalb der Gruppe nach Datum
ABC 01.12.2007 12:00
AB 12.12.2007 12:00 2. Gruppe mit Sortierung innerhalb der Gruppe nach Datum

Schaffe ich diese Sortierung, ohne das ich für die Gruppen nochmal extra Felder anlegen muss um diese dann dort seperat zu sortieren?

Eine Sortierung allein nach Name oder allein nach Datum ist kein Problem aber eine ressourcenschonde Sortierung nach Gruppen und innerhalb der Gruppen nochmal nach Datum fällt mir nicht ein. Jemand eine Idee?
 
Hi.

Du mußt lediglich den operator< für die Objekte definieren:
C++:
bool operator< (const Object& o1, const Object& o2) {
  if (o1.name < o2.name) return true;
  else if (o1.name == o2.name) {
    if (o1.datum < o2.datum) return true;
    else if (o1.datum == o2.datum) 
    // usw.
  }
}
Dieser Operator wird automatisch vom std::sort Algorithmus verwendet um die Elemente im Vektor zu sortieren.

Gruß
 
Vielen Dank für die Antwort.

Ich verwende zum sortieren std::sort.

Code:
std::sort(m_TempSortList.begin(), m_TempSortList.end(), SortByNameAndDate);

.
.

BOOL C_Manager::SortByNameAndDate( C_MyObject& a,C_MyObject& b) {

  if( a.GetName() > b.GetName() ) {
    return TRUE;
  } else if( a.GetName() == b.GetName() ) {
    if( a.GetDateReverse() + _T("_") + a.GetTime() > b.GetDateReverse() + _T("_") + b.GetTime() ) {
      return TRUE;
    } else {
      return FALSE;
    }
  } 
  return FALSE;
}

Das ist also fast derselbe Code wie bei dir und trotzdem sortiert er weiterhin nach Datum über alle Namen hinweg.
Nun hab ich mir schon einen anderen Algorithmus aus dem Kopf gequetscht und es funktioniert immer noch nicht. Kann doch nicht so schwer sein oder?
 
Hi.

Warum hast du das nicht gleich gepostet? :rolleyes:

Bist du sicher, das die Funktion überhaupt verwendet wird? Es kann eigentlich so nicht funktionieren, da du der sort Funktion keine Methode einer Klasse übergeben kannst (ohne Instanz? - oder ist die Methode statisch?)?

Wenn wirklich ausschließlich nach Datum, Zeit sortiert wird, dann müßte der Test (a.name == b.name) ja zu true ausgewertet werden?!

Gruß
 
Zuletzt bearbeitet:
Moin,

die Methode ist statisch ;-)

Unabhängig von meiner Funktion, bist du dir sicher, dass ich mit einem einzigem Durchlauf den vector sortiert bekomme?
Wobei gleiche Namen gruppiert werden sollen und innerhalb dieser Gruppen wiederrum das neueste Datum oben steht. Die Gruppe die das neueste Datum enthält, soll dann auch wieder ganz oben stehen.

Ich kann das Problem irgendwie nicht programmtechnisch Umsetzen.
 
Hi.
Unabhängig von meiner Funktion, bist du dir sicher, dass ich mit einem einzigem Durchlauf den vector sortiert bekomme?
Nicht mit einem einzigen Durchlauf, aber mit einem einzigen Aufruf von std::sort.
Wobei gleiche Namen gruppiert werden sollen und innerhalb dieser Gruppen wiederrum das neueste Datum oben steht. Die Gruppe die das neueste Datum enthält, soll dann auch wieder ganz oben stehen.

Ich kann das Problem irgendwie nicht programmtechnisch Umsetzen.
Überprüfe erstmal anhand von Beispielen, ob die Funktion richtig funktioniert.

Wie sieht die Klasse denn genau aus? Hast du entsprechend einen Zuweisungsoperator und Kopierkonstruktor definiert?

Gruß
 
Ein Aufruf von std::sort? Das wäre super.

Die Funktion arbeitet völlig korrekt. Die bereits implementierten Sortierungen nach Datum und nach Zeit (über alle Elemente) funktionieren sehr gut.

Code:
BOOL C_Manager::SortByDateAndTime( C_MyObject& a,C_MyObject& b) {
  return ( a.GetDateReverse() + _T("_") + a.GetTime() > b.GetDateReverse() + _T("_") + b.GetTime() ) ;
}

Code:
BOOL C_Manager::SortByName( C_MyObject& a,C_MyObject& b) {
  return ( a.GetName() + _T("_") + a.GetDateReverse() + _T("_") + a.GetTime() >  b.GetName() + _T("_") + b.GetDateReverse() + _T("_") + b.GetTime() );
}

Und so ist die Klasse aufgebaut:

Ich rufe einfach

Code:
std::sort(m_TempSortList.begin(), m_TempSortList.end(), SortByDateAndTime);

vobei m_TempSortList so definiert ist:

Code:
std::vector <C_MyObject> m_TempSortList;

vielleicht noch etwas anders erklärt. Ich schicke eine Liste mit zu sortieren Elementen in eine Funktion, die schauffelt mir die Elemente aus meiner CList in einen vector um std::sort zu benutzen. Elemente sortiert, dann werden die Objekte wieder in eine CList zurück geschauffelt und FERTIG. Die Klasse C_MyObject selbst hat keinen Zuweisungsoperator oder CopyConstructor.
 
Hi.
Und so ist die Klasse aufgebaut:
Fehlt da nicht irgendwie etwas?!
Die Klasse C_MyObject selbst hat keinen Zuweisungsoperator oder CopyConstructor.
Warum? Braucht die Klasse keine? Und wozu hast SortByName und SortByDateAndTime Funktionen gepostet? Die sind doch völlig irrelevant. Poste lieber mal konkret, an einem Beispiel, mit Beispieldaten, und der Ausgabe wie sortiert wird - also was du eingibst und was dann herauskommt. Diese einzelnen Code-Bruchstücke nützen nichts.

Hier mal ein Beispiel:
C++:
#include <iostream>
#include <algorithm>
#include <string>
#include <vector>
#include <iterator>
#include <functional>

using namespace std;


class Obj 
{
  string name;
  int value;
  string date;
  
  friend bool operator< (const Obj&, const Obj&);
public:
  
  Obj(const string& n, int v, const string& d) : name(n), value(v), date(d)
    {
    }
  
  string get_name() const
    {
      return name;
    }
  
  int get_value() const
    {
      return value;
    }

  string get_date() const
    {
      return date;
    }
};

ostream& operator<< (ostream& out, const Obj& o) 
{
  out << o.get_name() << " [" << o.get_date() << "] : " << o.get_value() << endl;
}


bool operator< (const Obj& o1, const Obj& o2) 
{
  if (o1.name < o2.name) return true;
  else if (o1.name == o2.name) 
    {
      if (o1.date < o2.date) return true;
      else if (o1.date == o2.date) return (o1.value < o2.value);
    }
  return false;
}

int main() 
{
  vector<Obj> v;
  
  v.push_back(Obj("asd", 44, "2007.11.02"));
  v.push_back(Obj("asd", 33, "2006.10.01"));
  v.push_back(Obj("aaa", 4544, "2006.11.04"));
  v.push_back(Obj("abc", 444, "2006.11.04"));
  v.push_back(Obj("abc", 333, "2006.11.04"));
  v.push_back(Obj("asd", 44, "2007.11.01"));
  
  vector<Obj> vv(v.begin(), v.end());
  
  copy(v.begin(), v.end(),
       ostream_iterator<Obj>(cout));
  
  sort(v.begin(), v.end());
  
  cout << endl << endl << "sortiert:" << endl;

  copy(v.begin(), v.end(),
       ostream_iterator<Obj>(cout));

  cout << endl << endl << "umgekehrt sortiert:" << endl;
  
  sort(vv.begin(), vv.end(), not2(less<Obj>()));

  copy(vv.begin(), vv.end(),
       ostream_iterator<Obj>(cout));
}
Gruß
 
Erstmal vielen Dank für deine Klasse.
Ich glaube das meine Klasse bei dem Problem eigentlich gar nicht so wichtig ist, denn sie sieht fast genauso wie deine aus. Ein Konstruktor ein paar Get und Set Methoden und das war es.
Mir geht es mehr um den Sortieralgotihmus, der Aufbau der Klasse passt.


Hier ein paar Beispieldaten und wie es nach einer Sortierung aussehen soll:

Vor Sortierung
1. A201..., 18.12.2007
2. A163..., 17.12.2007
3. A200..., 13.12.2007
4. A200..., 14.12.2007
5. A201..., 16.12.2007
6. A200..., 20.12.2007
7. A163..., 16.12.2007

Nach Sortierung - Die Gruppe mit dem neusten Element von allen steht oben
1. A200..., 20.12.2007 |
2. A200..., 14.12.2007 | Gruppe 1 nach Datum, neustes oben
3. A200..., 13.12.2007 |
4. A201..., 18.12.2007 | Gruppe 2 nach Datum, neustes oben
5. A201..., 16.12.2007 |
6. A163..., 17.12.2007 | Gruppe 3 nach Datum, neustes oben
7. A163..., 16.12.2007 |

Ich habe mir gerade mal deine Klasse angeschaut, funktioniert alles wunderbar aber die Sortierung bezieht sich "nur" auf den Namen und dann erst auf das Datum. Mein Problem ist es nach Gruppen zu sortieren und dann nochmal diese Gruppen.
 
Zuletzt bearbeitet:
Ich glaube das meine Klasse bei dem Problem eigentlich gar nicht so wichtig ist, denn sie sieht fast genauso wie deine aus. Ein Konstruktor ein paar Get und Set Methoden und das war es.
Sag mal, kannst du mich oder willst du mich nicht verstehen. Das bringt doch alles nichts. Du drehst dich hier nur im Kreis. Was soll das? :mad: :mad: :mad:

Hast du dort Zeiger in der Klasse? Dann brauchst du einen Kopierkonstruktor und Zuweisungsoperator.
Mir geht es mehr um den Sortieralgotihmus, der Aufbau der Klasse passt.
Der Sortieralgorithmus wird doch von std::sort bereitgestellt. Was hat das mit deinem Programm zu tun?

Hier ein paar Beispieldaten und wie es nach einer Sortierung aussehen soll:
Wie es nach der Sortierung aussehen soll weiß ich. :mad: Du solltest ein echtes, konkretes Beispiel mit Beispielcode und der Ausgabe deines Programmes machen. :mad:

Gruß
 
Zurück