arithmetic operation on list::iterator? - c++

I got a list like this:
list<float> l;
And I know there are 10 elements in l, I want to take first 7 elements from l and assign them to a vector, so I tried to do it like this:
vector<float> v(l.begin(), l.begin()+7);
The code above can't compile, later I found out that, list doesn't support random access while vector does, so list::iterator doesn't support arithmetic operation?
If so, How could I finish the job mentioned above?

Use copy_n:
v.resize(7);
copy_n(l.begin(), 7, v.begin());

Related

how to use erase, partition and iterate together at once on vector of objects

~ i'm learning c++ on my own~
I have a class field vector of objects that I want to iterate through and erase things that don't meet a certain condition.
myVector[0] is {obj1= val 1, obj2= val 2, obj3= val3 }
.
.
.
myVector[i] is {obj1= val x, obj2= val y, obj3= valz }
my issue is in order to pass the value to predicate function i need to access the object id and value at that index. But I don't know how to implement it so that i iterates/ increments.
Or more specifically how to I pass that key value at each index ? I'm asking for syntax help.
something like this:
myVector.erase(std::partition(myVector.begin(),myVector.end(), predicate(myVector[i].obj1)),myVector.end());
obviously there is no way for me to increment i this way.
is there a way to do this without using a for loop
I'm not 100% sure I understand the question, because you seem to be worried about the indexes into the vector. If your predicate needs to look at the indexes and not just the items in the vector, that complicates things.
However, does this solve your problem?
#include <algorithm>
myVector.erase(
std::remove_if(myVector.begin(), myVector.end(), myPredicate),
myVector.end());
This is an example of the so-called "erase / remove idiom." The call to remove_if shifts the elements you want to keep forward in the list the appropriate amount but doesn't truncate the vector. Instead, it returns a pointer to the end of the list, which you can then pass to erase.
(Why can't we do this just a single call, instead of having the confusingly-named erase AND remove together? Because std::remove_if is part of <algorithm>, which consists of generic algorithms that work on anything that supplies the right sort of iterators, whereas erase is special to std::vector. Having a start/end pair of the right sort of iterators gives you enough functionality to do what remove_if does, but doesn't give you the ability to truncate the list directly.)
You can write this using a lambda if you don't want to break the predicate out into its own method. For instance:
myVector.erase(
std::remove_if(myVector.begin(), myVector.end(),
[](const auto & x) { return x.obj1 <= 0; }),
myVector.end());

How to copy whole vector into queue in reversed order?

My vector stores the numbers of the vertices of a certain graph in ascending order. I want to add these numbers to a queue in order to run BFS later in code, but I dont know how do that in nice and fast way. I want the solution to be clear for everyone to read and what I came with is in my opinion obscure.
Disclaimer - I use static casts because i hate seeing warnings when i work with Qt. Here's what did:
Using casual for loop to iterate in reverse order through the vector starting with size-1 ending when i equals -1. Because I'm using -1 as rule I need to cast everything on int which makes code ugly.
vector<unsigned> v;
v.pushback(2);
v.pushback(3);
v.pushback(5);
queue<unsigned> q;
for(int i = static_cast<int>(v.size()-1); i>=0; i--)
q.push(v[static_cast<unsigned>(i)];
Can someone tell me how pros do it? Cant find anything like "copy in reverse order" function that can start from .end()-1 element and copy all elements including .begin() one?
std::vector provides the functions rbegin and rend which return reverse iterators that you can use to iterate from the back to the front. Using those you can use std::for_each to iterate the vector and then use a lambda as the functor to push each element into the queue. That would look like
std::vector<int> v = {1, 2, 3};
std::queue<int> q;
std::for_each(v.rbegin(), v.rend(), [&q](auto el){ q.push(el); });

How to use lower_bound on vector of vectors?

I am relative new at C++ and I have little problem. I have vector and in that vector are vectors with 3 integers.
Inner vector represents like one person. 3 integers inside that inner vector represents distance from start, velocity and original index (because in input integers aren't sorted and in output I need to print original index not index in this sorted vector).
Now I have given some points representing distance from start and I need to find which person will be first at that point so I have been thinking that my first step would be that I would find closest person to the given point so basically I need to find lower_bound/upper_bound.
How can I use lower_bound if I want to find the lower_bound of first item in inner vectors? Or should I use struct/class instead of inner vectors?
You would use the version of std::lower_bound which takes a custom comparator (the versions marked "(2)" at the link); and you would write a comparator of vectors which compares vectors by their first item (or whatever other way you like).
Howerver:
As #doctorlove points out, std::lower_bound doesn't compare the vectors to each other, it compares them to a given value (be it a vector or a scalar). So it's possible you actually want to do something else.
It's usually not a good idea to keep fixed-length sequences of elements in std::vector's. Have you considered std::array?
It's very likely that your "vectors with 3 integers" actually stand for something else, e.g. points in a 3-dimensional geometric space; in which case, yes, they should be in some sort of class.
I am not sure that your inner things should be std::vector-s of 3 elements.
I believe that they should std::array-s of 3 elements (because you know that the size is 3 and won't change).
So you probably want to have
typedef std::array<double,3> element_ty;
then use std::vector<element_ty> and for the rest (your lower_bound point) do like in einpoklum's answer.
BTW, you probably want to use std::min_element with an explicit compare.
Maybe you want something like:
std::vector<element_ty> vec;
auto minit =
std::min_element(vec.begin(), vec.end(),
[](const element_ty& x, const element_ty&y) {
return x[0] < y[0]));

C++ Vectors not performing as intuitively as I thought

I've been trying to learn how to use vectors in c++, and they seem much more complicated in java. In order to add items to a vector, I've had to use an iterator. What I'd like to be able to do is just use add remove functions and loop over them as in java. Is this possible? I'm trying to achieve something like the line I marked with an error below : insert(index 3, number 13), but this throws an error. Thanks in advance.
vector<int> myvector(0,0);
vector<int>::iterator it;
it = myvector.begin();
int q = 0;
for(it=myvector.begin();q<16;q++){
it = myvector.insert (it, q);
}
myvector.insert(3,13); //ERROR
You got advice above how to populate the vector.
If you want to insert something at specific index, you can do the following
//similar to myvector.insert(3,13); //ERROR
myvector.insert( myvector.begin()+3, 13);
The code above will insert 13 before element #3 so that 13 becomes element #3 (numeration starts with 0, so "begin" corresponds to element #0).
To replace element #3 with 13, you simply use
myvector[3] = 13;
Here is the link where you can learn about the C++ STL(Standard Template Library), such as: vector, queue, stack, list etc.

How to ensure an STL algorithm only iterates through a certain number of elements in a container?

I need to return the bottom 10 elements in a map using a for_each algorithm. For some reason map iterators do not have random access so I cannot use:
std::for_each(std::map.end(), std::map.end()-10, <lambda>);
I can use the -- operator on the iterators, but I'd rather not use ten of those!
So can someone let me know if there is a way to specify that the algorithm should only consider 10 of the elements?
Use auto x = your_map.end(); std::advance(x, -10);.
Note that as you have the iterators now, however, that won't do much good. You need the beginning of the range first -- if you use whatever.end() as the first parameter to for_each, it won't work correctly.
If you want to iterate through the map in reverse order, you could use:
auto s your_map.rbegin();
advance(s, 10);
std::for_each(s, your_map.rend(), ...);
In C++11 you can use std::advance(iter, dist) instead of calling ++ or -- ten times. To go forward, pass positive dist; to go backward, pass a negative dist:
auto ten_before(map.end());
std::advance(ten_before, -1);
std::for_each(std::map.end(), ten_before, -10), <lambda>);
std::advance as the other answers recommend will work. But in C++11 it's more convenient to use std::prev, which returns the resulting iterator instead of changing the given iterator, so it can be used in a one-liner:
std::for_each(std::prev(mymap.end(), 10), mymap.end(), func);
Note: I fixed the order of iterators above, you had the iterators backwards in your example.
If you want to iterate the last 10 items in reverse order, starting from the last element, you can use reverse iterators and std::next:
std::for_each(mymap.rbegin(), std::next(mymap.rbegin(), 10), func);