Bereiche aus vector<struct> nach vector kopieren



  • Sorry für den Titel, lässt sich blöd beschreiben...

    ich habe eine struct in der art:

    typedef struct{
    int a;
    double b;
    }s;

    und einen vector davon:

    vector <s> v;

    jetzt möchte ich die double-werte aus v in einen vector <double> v2 kopieren... gibts da eine angenehme lösung 😕

    bräuchte sowas wie:

    v2.assign(v.begin()->b,v.end()->b); //was natürlich nicht so geht 😞



  • typedef struct
    {
        int a;
        double b;
    
        operator double()
        {
            return b;
        }
    }s;
    
    v2.assign(v.begin(),v.end());
    

    das würde gehen.. Alleedings sollte man sich genau überlegen warum man es so braucht.
    solche „versteckte“ Konvertierungen können später zu einem Problem werden.



  • Ja.. also wenn das unbedingt ein Einzeiler mit Hilfe der Standardbibliothek werden soll, kannste dir bestimmt irgendwas mit std::transform und Lambdas basteln. Ob das allerdings sinnvoll ist wage ich zu bezweifeln, die kleine .push_back()/ = Schleife wird dich schon nicht überfordern. 😉



  • Huh, das mit dem Operator kannte ich noch gar nicht 😮 funktioniert aber auch so irgendwie nicht...

    Einzeiler wäre schon von vorteil, bzw. einfach schöner 😉

    ansonsten würde ich dan freilich ne schleife nehmen. Wollte nur vorher klären, ob es da keine "standartfunktion" gibt, die ich nur mal wieder nicht finde...



  • #include <vector>
    
    struct test
    {
    	int a;
    	double b;
    
    	test( int i, double d )
    		: a( i ), b( d )
    	{}
    
    	test() : a( 0 ), b( 0.0 ) {}
    
    	operator double()
    	{
    		return b;
    	}
    
    	operator int()
    	{
    		return a;
    	}
    };
    
    //und dann in main..
    	std::vector< test > testA;
    	testA.reserve( 20 );
    	for ( int i = 0; i < 20; ++i )
    	{
    		testA.push_back( test( i, i * 2 * 3.14 ) );
    	}
    	std::vector< double > dtest;
    	dtest.assign( testA.begin(), testA.end() );
    

    bei mir funktioniert alles..



  • ungetestet:

    vector<s> v;
    vector<double> d;
    
    //einzeller
    for(auto& e: v) d.push_back(e.b);
    


  • Sind Links zu solchen Seiten in diesem Forum erlaubt?

    Falls es sich bei den Seite hinter diesen Links um Rezepte-Webseiten oder Ähnliches handelt dann könnt ihr diesen Post ignorieren.



  • In C++03 ginge Folgendes:

    #include <algorithm>
    #include <functional>
    #include <iostream>
    #include <iterator>
    #include <vector>
    
    class s {
    public:
      inline s(int a, double b) : a_(a), b_(b) { }
    
      inline int    a() const { return a_; }
      inline double b() const { return b_; }
    
    private:
      int a_;
      double b_;
    };
    
    int main() {
      std::vector<s     > v_s;
      std::vector<int   > v_a;
      std::vector<double> v_b;
    
      v_s.push_back(s(1, 2.0));
      v_s.push_back(s(2, 3.1));
      v_s.push_back(s(3, 4.2));
      v_s.push_back(s(4, 5.3));
    
      std::transform(v_s.begin(), v_s.end(), std::back_inserter(v_a), std::mem_fun_ref(&s::a));
      std::transform(v_s.begin(), v_s.end(), std::back_inserter(v_b), std::mem_fun_ref(&s::b));
    
      std::copy(v_a.begin(), v_a.end(), std::ostream_iterator<int   >(std::cout, " "));
      std::cout << '\n';
      std::copy(v_b.begin(), v_b.end(), std::ostream_iterator<double>(std::cout, " "));
      std::cout << '\n';
    }
    

    Allerdings muss man, wenn man die Methoden a und b überlädt (etwa void a(int a_neu) und void b(double b_neu) einführt) von Hand auflösen, welches &s::a bzw. &s::b man meint (per static_cast, beispielsweise).



  • SvenStueck schrieb:

    ich habe eine struct in der art:

    typedef struct{
     int a;
     double b;
    }s;
    

    Du weißt, dass Du das in C++ auch ohne typedef aufschreiben kannst, ja?

    SvenStueck schrieb:

    vector <s> v;
    

    jetzt möchte ich die double-werte aus v in einen vector <double> v2 kopieren... gibts da eine angenehme lösung 😕

    Da gibt's viele Wege. Wenn Du selbst keine Schleife schreiben willst, könntest Du das über std::transform, einen back_inserter und boost::bind machen:

    transform( svec.begin(), svec.end(),
               back_inserter(dvec),
               bind(&s::b, _1) );
    

    Edit: Oops! Das ist ja in etwa das, was seldon auch schon vorschlug. Das hatte ich übersehen...

    Oder du könntest Dir per Boost zwei transform_iterator en erzeugen und die bei vector<double>::assign reinstecken.

    Verwendest Du C++11, könnte man bind durch einen Lambda-Ausdruck ersetzen oder gleich die for-range Schleife nehmen, so wie es knivel gezeigt hat -- eventuell noch mit einem dvec.reserve(svec.size()) vorher.


Anmelden zum Antworten