Efficiently iterate over vectors consistently c++ [closed] - c++

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 4 years ago.
Improve this question
I have n vectors and I need to iterate over all of them consistently.
I mean that first I need to iterate over all elements of first vector then to iterate over all elements of second vector and so on.
I have task to compare all elements consistently including the last element of k-1'th vector and first element of k'th vector.
I know the solution where I first concatanete all this vectors in one big final vector and then iterate over final vector.
But it seems to me that this solution wastes a lot of memory and time.
Please help me to find more optimized solution.
If it exists.
For example, with complexities: O(1) additional memory and O(n) time .

A simple approach would be to use two nested loops.
In C++11 and later, simply do
std::vector<std::vector<int> > vec;
// some code that sets up the vectors in vec
for (auto &v : vec) // iterate over the vectors in vec
{
for (auto &e : v) // iterate over the elements of v
{
// do whatever is needed to element e
}
}
If need be, v and e may be const qualified (to indicate not changing the vectors or their elements). The total number of iterations will be the number of elements of the contained vectors. The additional memory usage will be (at any point in time in the inner loop) two sets of references - one set for controlling the inner loop and one for the outer loop (i.e. no copies of the vectors or elements themselves).
Before C++11, the above loops can be rewritten less verbosely using for loops that work with iterators rather than ranges;
for (std::vector<std::vector<int> >::iterator v(vec.begin()), vend(vec.end());
v != vend; ++v)
{
for (std::vector<int>::iterator e(v->begin()), eend(v->end());
e != eend; ++e)
{
// do whatever is needed to element *e
}
}
Note the need to dereference iterators in this form.

If you only need something that can be iterated over, you probably want something like ranges::view::concat
Given N source ranges, produce a result range that is the concatenation of all of them.
This doesn't copy any values, so is O(1) storage and O(1) time.
If the thing you need is exactly std::vector<MyClass>, then you are out of luck, you will have to populate a vector with all the values.

Related

Is there any advantage of using a range for loop rather than an iterator? [closed]

Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 1 year ago.
This post was edited and submitted for review 7 months ago and failed to reopen the post:
Original close reason(s) were not resolved
Improve this question
for (auto& i : just_a_vec )
Or an iterator for loop.
for (std::vector<std::string>::iterator it = just_a_vec.begin(); it < just_a_vec.end(); it++)
Iterators predate range-based for loops, so they used to be the only of these two alternatives available. Nowadays, range-based for has mostly replaced iterators when dealing with a simple loop.
However, iterators can be used in various other contexts as well. For example, you can do std::sort(v.begin(), std::next(v.begin(), 5)) to sort the first five elements of a vector while leaving the rest of it alone.
Going back to iterating over a whole container:
If you can accomplish what you want with a range-based for, then it leads to more legible code, so they are preferable by default.
If you need iterators for some reason, such as using an algorithm that requires them, or because you need to jump ahead or back while iterating, then use those instead.
Also: In the later case, you can/should still use auto when declaring the iterator:
for(auto it = just_a_vec.begin(); it < just_a_vec.end(); it++) {
}
Edit: as asked: here's a simple, if a bit contrived, example where an iterator-based loop can still be useful:
// adds all values in the vector, but skips over twos values when encountering a 0
// e.g.: {1,2,0,4,5,2} => 5
int my_weird_accum(const std::vector<int>& data) {
int result = 0;
for(auto it = data.begin(); it != data.end(); ++it) {
auto v = *it;
result += v;
if(v == 0) {
// skip over the next two
assert(std::distance(it, data.end()) > 2);
std::advance(it, 2);
}
}
return 0;
}
Quick personal answer: Its somewhat sylistic and based on what version of c++ you are using. I typically prefer range based, but there are certainly moments iterators shine as well. Add both to your toolchest. For further reading.
Here is a list of other SO answers that get more into the performance and use cases.
What's the difference between iterator syntax in range-based loops for STL containers
Is the ranged based for loop beneficial to performance?
range based for loop vs regular iterator for loop
For further information. Google
Range vs iterator loop c++

how to gain access of vector elements for mathematical use? [closed]

Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 5 years ago.
Improve this question
newbie programmer here.
I have a vector with double values in it.
vector<double> P = {205.65,205.7,205.5,205,203.65,200.70...}
now I want to store the difference between two random element in a separate container.
I don't want a loop, there is no order in subtraction. I just want to know how can i subtract one element from another element and store the result in a different container.
Well, Q.push_back(P[i] - P[j]) is one way.
Q is a container (e.g. std::vector<double>) that supports push_back.
i and j are size_t types within the range of your vector P. P[i] is accessing the ith element of P. Note that the indexing starts at 0.
Finally, note that i and j need to index valid elements of the container: if they are outside the container's range then the program behaviour is undefined. Quite often that can be a silent effect insofar there is no immediate runtime failure, but it can have potentially hazardous consequences such as overwriting values of adjacent variables in memory! Some programmers therefore sacrifice a little performance and use P.at(i) in place of P[i] as the former is required by the C++ standard to throw an exception if an out-of-range access is attempted.
Let us say you want difference between the elements at positions i and j.
Step 1: Let us define a new 2D vector using the following statements:
vector <double> diff2(P.size());
vector < vector <double> > diff(P.size(),diff2);
Note that: diff [i] [j] will hold the value of P [i] - P [j];
Step 2: Now enumerate the vector diff as:
diff[i][j] = P[i] - P[j];
Note that: i and j are the indices of the elements you want to subtract. The indexing starts from 0.
Example: diff [1] [3] = P [1] - P [3] = 205.7 - 205 = 0.7

Only Move Iterator Once

I'm trying to find a way to improve my answer here. Let's simplify the question to say: I want to partition the input container, lets call it foo, into a vector of vectors of size STEP, the last of these vectors shall have a smaller size if there were less than STEP elements remaining in the input container, let's call this partitioned container bar.
I don't want to iterate over my input or output range multiple times. The element of the problem I'm trying to solve are simply:
Append bar with a constructed vector of size min(STEP, distance(it, foo.end())
Have the it point to advance(it, size(bar.back())) after constructing the container
Do this vector construction in-place
The translation of my answer to the confines of this problem is:
auto it = cbegin(foo);
for (auto i = size(foo); i > STEP; i -= STEP) {
bar.push_back(decltype(bar)::value_type(STEP));
for (auto internalIt = bar.back().begin(); internalIt != bar.back().end(); ++internalIt, ++it) {
*internalIt = *it;
}
}
bar.push_back(decltype(bar)::value_type(it, cend(foo)));
The problem is this line: bar.push_back(decltype(bar)::value_type(STEP)) I'm allocating the vector and 0-initializing it's components. Is there a better way to do this, under which I still would only iterate over the input and output ranges once?
bar.push_back(decltype(bar)::value_type{}); // or bar.resize(bar.size() + 1); if you prefer
bar.back().reserve(STEP);
while (bar.back().size() < STEP) {
bar.back().push_back(*it);
++it;
}
It's a stroke of bad luck that std::copy_n returns the advanced output iterator, when what you need to keep is the advanced input iterator, otherwise you could use that in place of the loop (using std::back_inserter to get the destination iterator).
Feel free to use a counter variable if you're concerned about the performance of bar.back().size()!

Different iterator for for loop in one code [closed]

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 6 years ago.
Improve this question
I am creating function, which takes a vector of operators( different matrices). Operators can be provided in different ordering ( from the smallest to biggest or other way around).
I need to create for loop based on ordering
for(auto tr = operators.begin(); tr != operators.end() ; ++tr )
or
for(auto tr = operators.end(); tr != operators.begin() ; --tr )
content inside of loop stays same
is there any way how to do this automatically? maybe based on some help input parameter?
You can support this by having your function consume a pair of iterators (a "range") instead of a complete matrix or vector. For example:
template <typename Iterator>
void print(Iterator begin, Iterator end) {
for(auto tr = begin; tr != end; ++tr)
; // ...
}
This way, you can pass any sort of range in: forward, reverse, or others. This is how much of the STL is designed.
If you use a std::vector for example, you'd invoke the above like so:
std::vector<int> vec;
print(vec.begin(), vec.end()); // forward
print(vec.rbegin(), vec.rend()); // reverse
Although, technically, an end() iterator can often be decremented and dereferenced safely, you are relying on specific properties that not all iterators are guaranteed to have.
A number of standard containers [some introduced in C++11 do not] have both forward iterators (which iterate through elements in order) and reverse iterators (which iterate over elements in the opposite order). The counterparts of begin() and end() are rbegin() and rend() respectively.

How to use iterator to iterate a 2D vector? [closed]

Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
Questions concerning problems with code you've written must describe the specific problem — and include valid code to reproduce it — in the question itself. See SSCCE.org for guidance.
Closed 9 years ago.
Improve this question
all
I am using vector in C++ STL to store my data. I pass and return them into and from functions. However, as the data size grows, the program is slower and slower. Thus I am updating the codes to an "iterator version".
What I want to archieve is that use iterators to pass, return and iterate STL vectors.
I am now ok with the operations with 1-dimensional vector, just like manipulating the arrays. However, when it comes to 2-dimensional vector, I am a bit confused.
Can anyone show me a simple code example that how to iterate a 2D vector using STL iterator?
Many thanks in advance.
Regards
Long
You state that your basic problem is performance, right?
You assume that this is caused due to copying.
Perhaps there could be simpler solutions for your problem:
Check if vectors can be passed by (const) reference
Check if shared_ptr makes sense
Consider if move semantics can help
Perhaps compiler version or implementation prevent return value optimization
If you need to know the size of a vector, and have two iterators it1 it2,
std::distance(it1, it2);
will tell you the distance between them. This will happen to be the size if they are begin and end
If you have a function like
int work(std::vector<int> items)
{
//...
}
this copies the vector items, so will use more RAM and take longer.
Sending a const ref instead will not copy the vector. Making it const stops you changing it, which might not help you, but you haven't posted any code so I don't know what you want to do.
int work(const std::vector<int> & items)
{
//...
}
Well its already somewhere on stackoverflow
But if you don't want to search here it is :
std::vector<std::vector<int> > vec{ {1,2,3},{4,5,6}};
//Simplest Way:- (C++11)
for(auto row:vec)
{
for(auto col:row)
std::cout<<col<< " ";
std::cout<<std::endl;
}
//OR Using iterator
std::vector<std::vector<int> >::iterator r;
std::vector<int>::iterator c;
for (r = vec.begin(); r != vec.end(); r++) {
for (c = r->begin(); c != r->end(); c++) {
std::cout<<*c<< " ";
}
std::cout<<std::endl;
}
Can get distance only between two iterators of same container
std::vector<int>::iterator s = v2.begin(); //Can be any start
std::vector<int>::iterator e = v2.end(); // Can be any end
std::cout<<"Distance :"<<std::distance(s,e)<<std::endl;