Thread: Can I use std::copy to take the projection of a vector<MyStruct> onto vector<T> ?

  1. #1
    Registered User FortranLevelC++'s Avatar
    Join Date
    May 2013
    Location
    United States
    Posts
    81

    Can I use std::copy to take the projection of a vector<MyStruct> onto vector<T> ?

    Hello, I have asked a similar question before, but this one is slightly different.

    If I have a vector of structures vector<S>, it is possible to use std::sort in order to sort this vector according to only one of the elements of the struct S, and this is can be done by passing a comparison function as the third argument of std::sort.

    For example, here is the code that sorts vector<S> by inserting a lambda function to control std::sort:

    Code:
    
    // sort algorithm example
    #include <iostream>     // std::cout
    #include <algorithm>    // std::sort
    #include <vector>       // std::vector
    #include  <string>
    
    
    
    
    struct S {
       int myInt;
       float myFloat;
       string myString;
    };
    
    
    int main () {
    
    
    
    
       vector<S> vec;
       vector<S> copyOfVec;
       S tempS;
    
    
    
    
       for(int k=0; k<10; k++){
          tempS.myInt= k;
          tempS.myFloat=(float)( sqrt(2.0)+k);
          tempS.myString=to_string(k*20); // this std function converts numbers to string, but it is new, and exists only in C++0x
          vec.push_back(tempS);
       }
    
    
       copyOfVec.resize(vec.size());
    
    
       copy(vec.begin(), vec.end(), copyOfVec.begin() ); // copy vec onto copyOfVec starting at the beginning of copyOfVec
       sort(copyOfVec.begin(), copyOfVec.end(), [](const S & S1, const S & S2){ return( S1.myInt > S2.myInt ) ; } ) ; // note the greater than sign ">" to make descending order
    
    
    
    
       for(int k=0; k<vec.size(); k++){
          cout<< " vec[k].myInt = " <<  vec[k].myInt << endl;
       }
    
    
       cout <<" ----------------- " << endl;
    
    
       for(int k = 0; k<copyOfVec.size(); k++){
          cout << " copyOfVec[k].myInt = " << copyOfVec[k].myInt << endl;
       }
    
    
    
    
      return 0;
    }
    Now my question is this: Just as we could sort vector<S> by using std::sort as described above, is there a way to use std::copy to copy ONLY according to one of the "coordinates" of S (for example the element myInt of S in the program above) from the vector<S> onto another vector<int>? In other words, can we use some version of std::copy to take the projection of vector<S> onto vector<int> by copying vec.myInt elements onto vector<int> tempIntVec?

    Many thanks.
    Last edited by FortranLevelC++; 09-03-2013 at 12:50 AM.

  2. #2
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    28,413
    There is std::copy_if for this purpose.
    Quote Originally Posted by Bjarne Stroustrup (2000-10-14)
    I get maybe two dozen requests for help with some sort of programming or design problem every day. Most have more sense than to send me hundreds of lines of code. If they do, I ask them to find the smallest example that exhibits the problem and send me that. Mostly, they then find the error themselves. "Finding the smallest program that demonstrates the error" is a powerful debugging tool.
    Look up a C++ Reference and learn How To Ask Questions The Smart Way

  3. #3
    Registered User FortranLevelC++'s Avatar
    Join Date
    May 2013
    Location
    United States
    Posts
    81
    Quote Originally Posted by laserlight View Post
    There is std::copy_if for this purpose.
    Many thanks!

    It seems that there are several options here.

    But I am still confused because the unary predicate function is supposed to return a bool type, not an arbitrary type that is in the struct S.

    This code is probably wrong, but this is what I had in mind. Is there a way to fix this?
    Code:
    vector<int> vec_projection;
    std::vector<int>::iterator result; 
    result = std::copy_if(vec.begin(), vec.end(), vec_projection.begin() ,
                  [](const S & s) ->int { return ( s.myInt ) ; } ) ;

    In this example, it seems that the iterator result ​ is not important because vec_projection "should" already have the necessary projected copy of S inside.

    Normally the std::copy_if unary predicate should return a boolean condition, not an integer, and so what I wrote must be wrong, but how else can I copy a coordinate of vector<S> onto vector<int>?
    Last edited by FortranLevelC++; 09-03-2013 at 01:57 AM.

  4. #4
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    28,413
    Oh, I misread your question. What you want, rather, is std::transform, since you are transforming a range of S objects into a range of int objects.
    Quote Originally Posted by Bjarne Stroustrup (2000-10-14)
    I get maybe two dozen requests for help with some sort of programming or design problem every day. Most have more sense than to send me hundreds of lines of code. If they do, I ask them to find the smallest example that exhibits the problem and send me that. Mostly, they then find the error themselves. "Finding the smallest program that demonstrates the error" is a powerful debugging tool.
    Look up a C++ Reference and learn How To Ask Questions The Smart Way

  5. #5
    C++まいる!Cをこわせ!
    Join Date
    Oct 2007
    Location
    Inside my computer
    Posts
    24,654
    Code:
    std::vector<int>::iterator result;
    result = std::copy_if(vec.begin(), vec.end(), vec_projection.begin() ,
                  [](const S & s) ->int { return ( s.myInt ) ; } ) ;
    Simplification (though it still does not work):
    Code:
    auto result =
    	std::copy_if(vec.begin(), vec.end(), vec_projection.begin(), [](const S & s)
    	{
    		return s.myInt;
    	});
    (You can deduce the return type. Furthermore, if your body of the lambda statement contains only a return statement, then you don't need to specify the return type.)
    Quote Originally Posted by Adak View Post
    io.h certainly IS included in some modern compilers. It is no longer part of the standard for C, but it is nevertheless, included in the very latest Pelles C versions.
    Quote Originally Posted by Salem View Post
    You mean it's included as a crutch to help ancient programmers limp along without them having to relearn too much.

    Outside of your DOS world, your header file is meaningless.

  6. #6
    Registered User FortranLevelC++'s Avatar
    Join Date
    May 2013
    Location
    United States
    Posts
    81
    Quote Originally Posted by laserlight View Post
    Oh, I misread your question. What you want, rather, is std::transform, since you are transforming a range of S objects into a range of int objects.
    Many thanks! Finally the std::transform is working.

    (But you did not misread my question: I am the one who made a mistake in the formulation of the question! When I originally wrote "is there a way to use std::copy to copy ONLY according to one of the "coordinates" of S ?" , this was misleading because it could have implied that I am really trying to copy by using a condition on the elements in S, not simply copying elements in S like vec_Projected[k] = vec[k].myInt. )
    Last edited by FortranLevelC++; 09-04-2013 at 08:08 PM.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Replies: 4
    Last Post: 07-05-2013, 02:30 AM
  2. Replies: 16
    Last Post: 06-13-2013, 06:15 PM
  3. Copy vector [need advice]
    By sugarfree in forum C++ Programming
    Replies: 12
    Last Post: 04-24-2010, 01:05 AM
  4. Quick vector copy
    By Nolens in forum C++ Programming
    Replies: 5
    Last Post: 12-07-2005, 03:39 PM
  5. vector won't copy correctly...
    By talz13 in forum C++ Programming
    Replies: 5
    Last Post: 10-18-2003, 07:35 AM