Auswahl aus Array mit Bedingung
-
Hallo,
ich habe eine Menge an Elementen, aus denen dasjenige, welches den niedrigsten Wert > 0 hat und ein zweites Kriterium erfüllt, ausgewählt werden soll.
Hab mal folgenden Pseudocode mit C Arrays:// Objekte MeineKlasse* Objekte[10]; ... // Vergleichswerte short Vergleichswert[10] = { 2, 5, 7, 3, 8, 1, 0, 9, 4, 6 }; // Bedingungen bool Bedingung[10] = { 0, 1, 0, 0, 1, 0, 0, 1, 1, 0 }; // Auswahl int ResultatIndex = -1; short KleinsterWert = 10; for(int i = 0; i < 10; i++) { if(Bedingung[i]) { if(Vergleichswert[i] < KleinsterWert && Vergleichswert[i] > 0) { KleinsterWert = Vergleichswert[i]; ResultatIndex = i; } } } if(ResultatIndex == -1) { cout << "Kein Wert entspricht den Kriterien." << endl; } else { cout << "Gesuchter Wert: " << *Objekte[ResultatIndex] << endl; }Mit dem Index kann ich dann das gesuchte Objekt fischen.
Das ganze soll dann aber mit mehr als 200 Werten funktionieren, anstatt nur mit 10, und soll eben dynamisch sein.
Nun dachte ich, dass das sicher schöner geht mit STL-Mitteln, doch weis ich grad nicht wie. Einfach die C Arrays mit Vectoren ersetzen?Wäre für eventuelle Tipps sehr dankbar

-
Wenn du die Arrays durch Vectoren ersetzt, geht es schonmal dynamisch. Eventuell könntest du noch die Algorithmen der STL einbauen, aber im Moment bin sich überfragt, welcher dafür geeignet ist (evt. min_element() mit einem speziell angepassten Vergleichsoperator).
-
Also ich würde auf jeden Fall std::vector nehmen. Der ist dynamisch und bietet Zugriffsmöglichkeiten wie ein Array.
Zum Suchen bietet sich eigentlich std::find_if() an. In deinem Beispiel sieht es aber so aus, als benötigtest du den Index für den Vergleichswert. Da wird find_if() wohl nicht funktionieren.
-
Danke, das sind schonmal zwei gute Stichworte.
Schau mich mal bei den Algorithmen der STL um, ob da was passt.
Weitere Vorschläge sind natürlcih willkommen
-
Hallo nochmal
Also so ganz kapier ich das nicht.
find_if liefert einfach das erste zurück, aber nicht das mit dem kleinsten Wert. min_element sieht gut aus, es gibt aber kein min_element_if oder?
min_element benutzt ein Predicate oder den operator<. Ich müsste wohl ein eigenes Predicate machen und da die if Abfrage einbauen. Aber, ich hab die Vergleichswerte und Bedingungen ja nicht im Objekt, also extern. Wie kann ich darauf zugreifen?Kann man solche Algorithmen selber auch machen? Gibs dafür Anleitungen?
Sorry, steh grad bisserl aufm Schlauch..
-
Hier ne kleinigkeit zum spielen:
#include "stdafx.h" #include <iostream> #include <vector> #include <functional> #include <algorithm> #include <time.h> using namespace std; // Prüft auf kleiner Wert und > 0 template<class Type> struct lessgreaterzero : public binary_function <Type, Type, bool> { bool operator()( const Type& i, const Type& a ) const { return i < a && i > 0; } }; int main(int argc, char* argv[]) { std::vector<int> var ; //------------------------------------------------------------------------------------- // Vector befüllen mit Zuallswerten und am Anfang eine 0 um zu prüfen ob die Funktion oben geht srand(static_cast<int>(time(NULL))); var.push_back(0); // Testen ob das > 0 klappt for(int i = 0; i < 100;++i) var.push_back(rand()); //------------------------------------------------------------------------------------- // Element suchen das passt int index = -1; // Index auf -1 um zu zeigen, das nichts gefunden wurde vector<int>::iterator pos; // Das Ergebnis von find_if speichern pos = find_if(var.begin(),var.end(),bind2nd(lessgreaterzero<int>(),4000)); // Werte prüfen auf < 40000 if(pos != var.end()) // Wenn das Ende vom Vector erreicht, wurde nichts gefunden index = distance(var.begin(),pos); // Ansonsten die Distanz von anfang bis gefundenen iterator errechnen //------------------------------------------------------------------------------------- // Alle Positionen die passen speichern und ausgeben vector<int> positionen; pos = var.begin(); do { pos = find_if(pos,var.end(),bind2nd(lessgreaterzero<int>(),4000)); if(pos == var.end()) break; positionen.push_back(distance(var.begin(),pos)); }while(pos++ != var.end()); // Alle index ausgeben die passen cout<<"vector:\n"<<endl; copy(var.begin(),var.end(),ostream_iterator<int>(cout,"\t")); cout<<"\npositionen:\n"<<endl; copy(positionen.begin(),positionen.end(),ostream_iterator<int>(cout,"\t")); return 0; }
-
Danke, ja das sieht gut aus.
Ich bräucht wohl etwas im Stil von:template <class ForwardIterator, class BinaryPredicate, class Predicate> ForwardIterator min_element_if (ForwardIterator first, ForwardIterator last, BinaryPredicate comp, Predicate pred) { ForwardIterator result = last; for (ForwardIterator = it ; it != last; it++) { if (pred(it)) if (comp(it, result)) result = it; } return result; }und dann noch zwei so structs
template <class T> struct less_greater_zero : public binary_function <T, T, bool> { bool operator() (const T& arg1, const T& arg2) const { return i > 0 && arg1 < arg2; } };template <class T> struct has_item : public unary_function <T, bool> { bool operator() (const T& arg) const { // so und hier brauch ich Zugriff auf Bedingung[arg's Index] ausm ersten Post??? } };Wie kann ich dem struct has_item Zugriff auf das bool-Array geben?
Und wie komm ich an den Index von arg dran?Wenn das so ginge wär super, macht Spass

-
uups, sorry
return i > 0 && arg1 < arg2;
sollte
return arg1 > 0 && arg1 < arg2;
heissen
-
Wenn es wirklich noch von einem zweiten Array abhängt, könnte das hier zum spielen verleiten:
#include <iostream> #include <vector> #include <functional> #include <algorithm> #include <time.h> using namespace std; // Prüft auf kleiner Wert und > 0 template<class Type> struct lessgreaterzero : public binary_function <Type, Type, bool> { bool operator()( const Type& i, const Type& a ) const { return i < a && i > 0; } }; int main(int argc, char* argv[]) { std::vector<int> var ; std::vector<bool> bed; std::vector<int> posi; srand(static_cast<int>(time(NULL))); for(int i = 0;i < 100;++i) { int rnd = rand(); var.push_back(rnd); bed.push_back(rnd < rand()); } for(vector<bool>::iterator pos = bed.begin();pos != bed.end();++pos) { // Man könnte sich noch das ständige erzeugen der struktur ersparen if(*pos && lessgreaterzero<int>()(var[distance(bed.begin(),pos)],4000)) posi.push_back(distance(bed.begin(),pos)); } // Alle index ausgeben die passen cout<<"bed:\n"<<endl; copy(bed.begin(),bed.end(),ostream_iterator<int>(cout,"\t")); cout<<"vector:\n"<<endl; copy(var.begin(),var.end(),ostream_iterator<int>(cout,"\t")); cout<<"\npositionen:\n"<<endl; copy(posi.begin(),posi.end(),ostream_iterator<int>(cout,"\t")); }
-
Danke, Knuddelbaer, das du meinen Spieltrieb förderst

distance() wieder was gelernt :life:
Grübel...

Ich übergeb einfach nen Iterator auf den Bediungunsvector:template <class ForwardIterator, class BinaryPredicate, class PredicateIterator> ForwardIterator min_element_if (ForwardIterator first, ForwardIterator last, BinaryPredicate comp, PredicateIterator pred) { ForwardIterator result = last; for (ForwardIterator it = first; it != last; it++, pred++ ) { if (*pred) if (comp(*it, *result)) result = it; } return result; } //Aufruf position = min_element_if( Vergleichswert.begin(), Vergleichswert.end(), less_greater_zero, Bedingung.begin()Heureka?
ps: ich kompiliere grad im kopf :p
-
Da du eine direkte Zuordnung zwischen den beiden Werten (Zahl und Gültigkeit) hast, würde ich sie nicht in getrennten Arrays rumschleppen, sondern gemeinsam - also statt zweier Vectoren 'var' und 'bed' nur einen "vector<pair<int,bool> > var;" (da hast du auch die Gültigkeitsbedingung im Vergleich drin:
template<class Type> struct lessbed : public binary_function <pair<Type,bool>, pair<Type,bool>, bool> { bool operator()( const pair<Type,bool>& i, const pair<Type,bool>& a) const { return i.first < a.first && i.first*i.second > 0; } };
-
Die beiden Arrays sind aber unabhängig und werden unterschiedlich oft zu verschiedenen Zeiten und Quellen geändert. Von daher will ich die nicht zusammenfassen.
Aber trotzdem eine gute Idee, danke nochmal.