tags:

views:

221

answers:

4

I'm just trying to get more into stl semantics, and converting old loops over to algorithms where appropriate. I'm having trouble figuring out the best way to transform this loop into a call to copy. Any ideas?

    vector< vector<float> > rvec;
    const float * r[Max] = ...;

    // ...

    for (int ri=0; ri<N; ri++)
      for (int rj=0; rj<M; rj++)
        rvec[ri][rj] = r[ri][rj];
+2  A: 

Not sure you can do this with only the standard algorithms and no functors (and with those, the code is bound to grow significantly than above).

You know, sometimes a plain loop is just best. STL's algorithms are very nice, but since C++ doesn't have anonymous functions or built in lambdas (yet), taking perfectly readable code such as you show above and converting it to STL algorithms is more of an intellectual exercise than actual improvement,

Assaf Lavie
Agreed. Tossing iterators all over the place just to use STL's copy() isn't worth bloating the code you already have that does the job just as well.
Jeff L
anonymous Lambda's are part of the c++0x standard, much of which is already supported by current compilers. It may be worth trying to see if one works.
TokenMacGuy
+1. For most code, readability (== maintainability) trumps other concerns. OK, If you find yourself doing a lot of this, consider creating your own 2D (or n-D) copy<T>() function template.
j_random_hacker
I disagree... the STL libraries are really optimized and using iterators also makes the code better in terms of performance. What you guys are saying here is almost like saying that you prefer coding crappy code over clever and well thought code.
Partial
@Partial: I would agree, except that (a) he's talking about taking a bunch of working code and changing it, which carries a risk of introducing bugs, and (b) without lambdas the new code is undeniably less readable. Performance-wise, both will almost certainly be the same -- the only way a copy<>() call could be faster is if the library implementation somehow spreads the work across multiple CPUs, and to my knowledge no current library implementations do that. However that may become a compelling reason to prefer copy<>() in the future.
j_random_hacker
@j_random_hacker: If your are changing working code it will for sure cause a few bugs. So while your at it, why would you not take the time to use STL? The STL could actually reduce code... instead of using two loops you can use a single line to copy a vector to another vector. I don't understand why the code would become less readable. And anyway if there is some complicated code you should leave comments to explain what the code does!
Partial
In fact, even if the code isn't complicated you should always leave some comments.
Partial
@Partial: Can you transform both those loops to use STL algorithms/primitives *without* requiring the definition of functors? Sure, the inner loop could easily be changed to a single copy<>() -- and perhaps there is a small readability advantage to doing so -- but how would you manage the outer loop?
j_random_hacker
+6  A: 
rvec.resize(Max);
for (int i = 0; i < Max; ++i) {
  rvec[i].resize(M);
  std::copy(r[i], r[i] + M, rvec[i].begin());
}

If rvec itself and each vector in rvec already has the correct size, then resizing isn't needed.

Roger Pate
using vector iterators would make this faster
Partial
^^^^ that is not necessarily true.
ttvd
+1  A: 

In this case just leaving the code as is isn't so bad. Though if you wrote it multiple times abstracting it into a separate function would be a good idea. Another point to consider, any solution that doesn't reserve or resize will waste time copying where you don't need to.

Matt Price
+1. Good point about reserve()/resize() -- this will make a noticeable performance difference if used on large arrays or in tight loops. (I.e. it's probably not premature optimisation to consider doing these things.)
j_random_hacker
A: 

Here is an example I made a bit rapidly with iterators...

#include <algorithm>
using std::copy;
using std::for_each;
using std::random_shuffle;

#include <iostream>
using std::cout;
using std::endl;

#include <vector>
using std::iterator;
using std::vector;

void Write(int i)
{
    cout << i << endl;
}

int main()
{
    const short MAX_LIST = 1000,
       MAX_NUMBER = 100;
    float number = 0;
    vector<vector<float> > v (MAX_LIST),
            v2 (MAX_LIST);
    vector<float> list(MAX_NUMBER);

    //Fills list and fills v with list
    for(vector<vector<float> >::iterator v_iter = v.begin(); v_iter != v.end(); ++v_iter)
    {
     for(vector<float>::iterator list_iter = list.begin(); list_iter != list.end(); ++list_iter)
     {
      *list_iter = number;
      ++number;
     }
     *v_iter = list;
    }

    //write v to console
    for(vector<vector<float> >::iterator v_iter = v.begin(); v_iter != v.end(); ++v_iter)
    {
     for_each(v_iter->begin(), v_iter->end(), Write);
    }

    //copy v to v2
    cout << "Copying..." << endl;
    copy(v.begin(), v.end(), v2.begin());
    cout << "Finished copying!" << endl;

    cout<< "Shuffling..." << endl;
    random_shuffle(v2.begin(), v2.end());
    cout << "Finished shuffling!" << endl;

    //write v2 to console
    for(vector<vector<float> >::iterator v_iter = v2.begin(); v_iter != v2.end(); ++v_iter)
    {
     for_each(v_iter->begin(), v_iter->end(), Write);
    }
}
Partial
You were very explicit about your dependencies, but using std::iterator; may fail if you don't #include <iterator>. Instead of Write have you seen std::ostream_iterator?
Roger Pate
If I am not mistaken, vector already includes iterator and I am using a vector iterator. Therefore, I believe it shouldn't fail. On the other hand, using std::ostream_iterator could be a great option instead of Write!
Partial
This doesn't answer the question. The OP was trying to copy from a 2D array to a 2D vector. Your only call to std::copy copies a 2D vector to another 2D vector. It shows the usage of standard algorithms, but it doesn't help drewster much.
A. Levy