Can you please tell me how to do the following using STL algorithms?
// Create a vector of 50 elements, and assign elem value same as index value
std::vector<int> a(50);
for (int i = 0; i < a.size(); i++)
{
a[i] = i;
}
// Create another vector by copying a section of vector a
std::vector<int> b;
size_t ind = 20;
b.resize(a.size() - ind);
for (int i = 0; i < b.size(); i++)
{
b[i] = a[i+ind];
}
Essentially, I am trying to create a new vector b, from vector a, by skipping the first 'ind' elements of a.
I'd probably do it something like this:
std::vector<int> a(50);
// fill a with 0..N
std::iota(a.begin(), a.end(), 0);
size_t ind = 20;
// initialize `b` from elements of `a`:
std::vector<int> b{a.begin()+ind, a.end()};
You could use std::copy for the second part, but for the case at hand I'd prefer to initialize b from the iterators as I've done above.
With boost you could do the first part with initialization as well (see Jerry's answer).
auto r = boost::irange(0,50);
auto a = std::vector<int>(std::begin(r), std::end(r));
Eric Neibler's range library I think includes this type of thing and I fully expect it'll make it into C++17. Until then you have to use his or boost's as a third-party lib.
Use the
template <class InputIterator>
vector (InputIterator first, InputIterator last,
const allocator_type& alloc = allocator_type());
constructor as follows.
auto start = std::next(a.begin(), 20);
std::vector<int> b(start, a.end());
Related
In C++ we have functions like std::fill or std::fill_n which are convenient one-liner ways of filling pointer-arrays, vectors, std::arrays and other containers with values. Some containers also have their own fill methods to allow filling with a constant value. There are also the functions std::generate{_n} and std::iota, the former of which allows filling the elements using a generator function and the latter of which fills the range with indices.
What I am looking for is a similar solution - preferrably a one-liner solution and defined in the standard library - that allows filling the container with some function of the index. For example, this would be a solution for an array:
std::array<int, 100> arr;
for (std::size_t i = 0; i < 100; i++)
arr[i] = f(i);
where f(std::size_t i) is some function of the index.
Is there an integrated way of doing this?
You could use a stateful lambda:
std::array<int, 100> arr;
std::generate(arr.begin(), arr.end(), [i = std::size_t(0)]() mutable {return f(i++);});
But I think it makes the code more complex than it needs to be. Using a plain loop might be the best option.
I couldn't try this with a compiler since I couldn't find one with C++20 ranges, but something like this should work once compilers implement them:
std::ranges::transform(std::views::iota{1, arr.size()+1}, arr, f);
or, if you just want the sequence of generated values, just create a range of them with
auto const values = std::views::iota{1, arr.size()+1} | std::views::transform(f);
Until you have a C++20 compiler, you can use one of the range libraries, e.g. in Boost or Eric Nieblers ranges-v3
Consider writing your own STL-like function template, apply_idx_func(), for that:
template<typename FwdItor, typename F>
void apply_idx_func(FwdItor first, FwdItor last, F f) {
for (size_t idx = 0; first != last; ++first, ++idx)
*first = f(idx);
}
As an example:
auto main() -> int {
std::array<int, 10> arr;
// just adds 100 to the index
auto func = [](size_t idx) -> int {
return 100 + idx;
};
apply_idx_func(std::begin(arr), std::end(arr), func);
for (auto elem: arr)
std::cout << elem << ' ';
std::cout << '\n';
}
The output is:
100 101 102 103 104 105 106 107 108 109
If you always go through the whole array, you don't even have to use any stl function, just use range loop:
std::array<int, 100> arr;
int idx = 0;
for (auto& item : array)
item = f(idx++);
Another option is to use for_each (this can be more useful, if in the future you want to fill your array only partially)
#include <algorithm>
std::array<int, 100> arr;
int idx = 0;
std::for_each(begin(arr), end(arr), [&idx](int &n){ n = f(idx++); });
Unfortunately, in both cases, you have to have separate variable for index (here: idx)
#include <algorithm>
size_t i = 0;
std::generate_n(arr.begin(),arr.size(),[&i](){return f(i++);});
Or possibly in two steps:
#include <numeric>
std::iota(arr.begin(),arr.end(),0);
std::transform(arr.begin(),arr.end(),f);
With the help of boost we can do this in one step:
std::transform(
arr.begin(),
arr.end(),
boost::irange(0,arr.size()),
[](const auto& val,const auto& index){return f(index);}
);
https://www.boost.org/doc/libs/1_64_0/libs/range/doc/html/range/reference/ranges/irange.html
in my code I have a matrix of double like this:
double * * matrix=new double * [10];
for(int i=0;i<10;i++)
matrix[i]=new double[10];
I want to have NaN value in every cell of this matrix when I initialize it, is it possible to do automatically or the only solution is:
for(int i=0;i<10;i++)
for(int j=0;j<10;j++)
matrix[i][j]=nan("");
Is it possible to infer that when the matrix will costruct, it doesn't use the default constructor of double that insert, for every matrix[i][j], 0.0 value but insert nan("")?
double doesn't have a default constructor, i.e. double values are uninitialized by default.
To avoid explicitly implementing the loops, you can use std::vector :
#include <vector>
...
std::vector<std::vector<double>> matrix(10, std::vector<double>(10, nan("")));
or:
#include <vector>
using namespace std;
...
vector<vector<double>> matrix(10, vector<double>(10, nan("")));
First, strongly avoid using raw pointers in C++ yourself - it's almost always a bad idea. If there's no container class that fits, use std::unique_ptr. So your code becomes:
auto matrix = std::make_unique<double* []>(10);
for(int i=0;i<10;i++) {
matrix.get()[i]= std::make_unique<double []>(10);
}
This code is still not what you want. It's usually not a good idea to create your NxN matrix using N calls to new, or n constructions of a vector. Make a single allocation of NxN doubles, and then either wrap it in a class MyMatrix which supports a 2-parameter square-brace operator, i.e.
template <typename T>
class MyMatrix {
// etc. etc
double const T& operator[](size_type i, size_type j) const { return data_[i*n + j]; }
double T& operator[](size_type i, size_type j) { return data_[i*n + j]; }
}
or (not-recommended) have the pointers point into the single-allocation region:
size_t n = 10;
auto matrix_data = std::make_unique<double []>(n * n);
auto matrix = std::make_unique<double* []>(n);
for(int i=0;i<10;i++) {
matrix.get()[i] = matrix_data.get() + i * n;
}
in each of these cases you can later use std::fill to set all matrix values to NaN, outside of any loop.
The last example above can also be transformed into using vectors (which is probably a better idea than just the raw pointers if you're not using your own class):
size_t n = 10;
auto matrix_data = std::vector<double>(n * n);
auto matrix = std::vector<double*>(n);
for(auto& row : matrix) {
auto row_index = std::dist(row, matrix.begin());
row = &matrix_data[row_index * n];
}
Again, I don't recommend this - it's still a C-like way to enable a my_matrix[i][j] syntax, while using a wrapper class gets you my_matrix[i,j] without needing extra storage, with initialization to NaN or another value (in the constructor), and without following two pointers each time you access it.
If you want to use statically sized arrays you would be better off using std::array. For easier use of multi-dimenstional std::array you can use a template alias
template <class T, size_t ROW, size_t COL>
using Matrix = std::array<std::array<T, COL>, ROW>;
You can set the values in the matrix with std::array::fill, e.g.
Matrix<double, 3, 4> m = {};
m.fill(42.0);
You can also create a compile-time constant matrix object initialized with a default value to skip the initialization at runtime with a simple constexprfunction.
template<typename T, size_t R, size_t C>
constexpr auto makeArray(T&& x) {
Matrix<T,R,C> m = {};
for(size_t i=0; i != R; ++i) {
for(size_t j=0; j != C; ++j) {
m[i][j] = std::forward<T>(x);
}
}
return m;
}
auto constexpr m = makeArray<double, 3,4>(23.42);
I am going to repeat the advice given to prefer C++ constructs over C constructs. They are more type-safe and IMHO almost always more convenient to use, e.g. passing std::array objects as parameters is not different from any other objects. If you are coming from a C background and have no further C++ experience, I would recommend to read some tutorial text that does not first introduce C, e.g. The Tour of C++,
This code below doesn't work because I push_back the vectors a and b to the vector vector and then alter the vectors a and b. I want to alter the vectors a and b so that the vector vector suffers the same modifications. How do I do this?
#include <iostream>
#include <vector>
int main()
{
std::vector<std::vector<int>>vector;
std::vector<int>a;
std::vector<int>b;
vector.push_back(a);
vector.push_back(b);
for (int i = 1; i <= 10; i++)
a.push_back(i);
for (int i = 11; i <= 20; i++)
b.push_back(i);
std::cout << vector[1][0];
std::cin.get();
}
You can use std::reference_wrapper (since C++11).
std::reference_wrapper is a class template that wraps a reference in a copyable, assignable object. It is frequently used as a mechanism to store references inside standard containers (like std::vector) which cannot normally hold references.
e.g.
std::vector<std::reference_wrapper<std::vector<int>>> v;
std::vector<int> a;
std::vector<int> b;
v.push_back(a);
v.push_back(b);
for (int i = 1; i <= 10; i++)
a.push_back(i);
for (int i = 11; i <= 20; i++)
b.push_back(i);
std::cout << v[1].get()[0]; //11
LIVE
Note that if the vector has longer timelife than a and b, then when a and b get destroyed the references stored in the vector become dangled.
Create v (vector is not a good name since it shares with the library and makes the code confusing) to be a vector of vector pointers (since a vector of references is not possible):
std::vector<std::vector<int> *> v; //declare as vec of vec pointers
...
v.push_back(&a); //push_back addresses of a and b
v.push_back(&b);
...
std::cout << v.at(1)->at(0) //dereference and call at on the inner vec
Note that this can be dangerous if a or b go out of scope before v, as that will leave you with dangling pointers, a mess of undefined behavior and a murder time-consuming bugs.
The basic issue is that push_back copies its parameter to the end of the vector. To modify the object in the vector, you need to get a reference to it. One approach:
std::vector< std::vector<int> > my_vector;
my_vector.reserve(2); // Going over the allocation invalidates references
my_vector.push_back( std::vector<int>() );
std::vector<int> & a = my_vector.back();
my_vector.push_back( std::vector<int>() );
std::vector<int> & b = my_vector.back();
(I changed the name of the variable because using "vector" as a variable name tends to lead to confusion.)
If you can use C++17, there is a way to reduce the lines of code using emplace_back.
If you know the number of vectors ahead of time you can do it like this:
std::vector<std::vector<int>> v(2);
std::vector<int> &a = v[0];
std::vector<int> &b = v[1];
...
I want to use a special method to initialize a std::vector<unsigned int> which is described in a C++ book I use as a reference (the German book 'Der C++ Programmer' by Ulrich Breymann, in case that matters). In that book is a section on sequence types of the STL, referring in particular to list, vector and deque. In this section he writes that there are two special constructors of such sequence types, namely, if Xrefers to such a type,
X(n, t) // creates a sequence with n copies of t
X(i, j) // creates a sequence from the elements of the interval [i, j)
I want to use the second one for an interval of unsigned int, that is
std::vector<unsigned int> l(1U, 10U);
to get a list initialized with {1,2,...,9}. What I get, however, is a vector with one unsigned int with value 10 :-| Does the second variant exist, and if yes, how do I force that it is called?
there are at least three ways that you can do that. One was mentioned earlier by Brian
//method 1
generate(v.begin(), v.end(), [] { static int i {1}; return i++; });
You can also use std::iota if you are using c++11
//method 2
iota(v.begin(), v.end(), 1);
Or instead you can initialize your container with 1s and then do a partial sum on that. I don't think anybody will use this third method anyway :)
//method 3
vector<int> v(n, 1);
partial_sum(v.begin(), v.end(), v.begin());
Reread the paragraphs near there describing what each of the parameters are. Specifically, it should mention that i and j are not values, but iterators. This constructor is very commonly used to make copies of other types of containers. If you want to get a sequence of values, the Boost library provides a counting iterator, that does exactly what you want.
std::vector<unsigned int> numbers(
boost::counting_iterator<unsigned int>(0U),
boost::counting_iterator<unsigned int>(10U));
A non-boost way to do this with a self-incrementing iterator.
#include <vector>
#include <iostream>
#include <algorithm>
static int NUM_ITEMS = 10;
class gen_range {
public:
gen_range(int i) { idx = i; }
int operator()() { return (idx++); };
int idx;
};
int main() {
std::vector<int> x(NUM_ITEMS);
std::generate_n(x.begin(), NUM_ITEMS, gen_range(0));
for (int i=0; i < x.size(); i++) {
std::cout << x[i] << std::endl;
}
}
C++11:
std::vector<int> idxs (n);
std::generate_n (idxs.begin (), n, [] { static int i {1}; return i++; });
No, that variant does not exist. The second constructor initializes a vector from two iterators that point into another sequence.
Here is an example of the "two-iterator" constructor in action:
int fill_data[4] = { 1, 2, 3, 4 };
std::vector<int> v(fill_data, fill_data + 4);
This question already has answers here:
How do I sort a std::vector by the values of a different std::vector? [duplicate]
(13 answers)
Closed 9 years ago.
This is probably best stated as an example. I have two vectors/lists:
People = {Anne, Bob, Charlie, Douglas}
Ages = {23, 28, 25, 21}
I want to sort the People based on their ages using something like sort(People.begin(), People.end(), CustomComparator), but I don't know how to write the CustomComparator to look at Ages rather than People.
Obvious Approach
Instead of creating two separate vectors/lists, the usual way to handle this is to create a single vector/list of objects that include both names and ages:
struct person {
std::string name;
int age;
};
To get a sort based on age, pass a comparator that looks at the ages:
std::sort(people.begin(), people.end(),
[](auto const &a, auto const &b) { return a.age < b.age; });
In older C++ (pre C++11, so no lambda expressions) you can define the comparison as a member overload of operator< or else as a function-object (an object that overloads operator()) to do the comparison:
struct by_age {
bool operator()(person const &a, person const &b) const noexcept {
return a.age < b.age;
}
};
Then your sort would look something like:
std::vector<person> people;
// code to put data into people goes here.
std::sort(people.begin(), people.end(), by_age());
As for choosing between defining operator< for the class, or using a separate comparator object as I show above, it's mostly a question of whether there's a single ordering that's "obvious" for this class.
In my opinion, it's not necessarily obvious that sorting people would always happen by age. If, however, in the context of your program it would be obvious that sorting people would be done by age unless you explicitly specified otherwise, then it would make sense to implement the comparison
as person::operator< instead of in a separate comparison class the way I've done it above.
Other Approaches
All that having been said, there are a few cases where it really is impractical or undesirable to combine the data into a struct before sorting.
If this is the case, you have a few options to consider. If a normal sort is impractical because the key you're using is too expensive to swap (or can't be swapped at all, though that's pretty rare), you might be able to use a type where you store the data to be sorted along with just an index into the collection of keys associated with each:
using Person = std::pair<int, std::string>;
std::vector<Person> people = {
{ "Anne", 0},
{ "Bob", 1},
{ "Charlie", 2},
{ "Douglas", 3}
};
std::vector<int> ages = {23, 28, 25, 21};
std::sort(people.begin(), people.end(),
[](Person const &a, person const &b) {
return Ages[a.second] < Ages[b.second];
});
You can also pretty easily create a separate index that you sort in the order of the keys, and just use that index to read through the associated values:
std::vector<std::string> people = { "Anne", "Bob", "Charlie", "Douglas" };
std::vector<int> ages = {23, 28, 25, 21};
std::vector<std::size_t> index (people.size());
std::iota(index.begin(), index.end(), 0);
std::sort(index.begin(), index.end(), [&](size_t a, size_t b) { return ages[a] < ages[b]; });
for (auto i : index) {
std::cout << people[i] << "\n";
}
Note, however, that in this case, we haven't really sorted the items themselves at all. We've just sorted the index based on the ages, then used the index to index into the array of data we wanted sorted--but both the ages and names remain in their original order.
Of course, it's theoretically possible that you have such a bizarre situation that none of the above will work at all, and you'll need to re-implement sorting to do what you really want. While I suppose the possibility could exist, I've yet to see it in practice (nor do I even recall seeing a close call where I almost decided that was the right thing to do).
As others have noted, you should consider grouping People and Ages.
If you can't/don't want to, you could create an "index" to them, and sort that index instead. For example:
// Warning: Not tested
struct CompareAge : std::binary_function<size_t, size_t, bool>
{
CompareAge(const std::vector<unsigned int>& Ages)
: m_Ages(Ages)
{}
bool operator()(size_t Lhs, size_t Rhs)const
{
return m_Ages[Lhs] < m_Ages[Rhs];
}
const std::vector<unsigned int>& m_Ages;
};
std::vector<std::string> people = ...;
std::vector<unsigned int> ages = ...;
// Initialize a vector of indices
assert(people.size() == ages.size());
std::vector<size_t> pos(people.size());
for (size_t i = 0; i != pos.size(); ++i){
pos[i] = i;
}
// Sort the indices
std::sort(pos.begin(), pos.end(), CompareAge(ages));
Now, the name of the nth person is people[pos[n]] and its age is ages[pos[n]]
Generally you wouldn't put data that you want to keep together in different containers. Make a struct/class for Person and overload operator<.
struct Person
{
std::string name;
int age;
}
bool operator< (const Person& a, const Person& b);
Or if this is some throw-away thing:
typedef std::pair<int, std::string> Person;
std::vector<Person> persons;
std::sort(persons.begin(), persons.end());
std::pair already implement comparison operators.
It doesn't make sense to keep them in two separate data structures: if you reorder People, you no longer have a sensible mapping to Ages.
template<class A, class B, class CA = std::less<A>, class CB = std::less<B> >
struct lessByPairSecond
: std::binary_function<std::pair<A, B>, std::pair<A, B>, bool>
{
bool operator()(const std::pair<A, B> &left, const std::pair<A, B> &right) {
if (CB()(left.second, right.second)) return true;
if (CB()(right.second, left.second)) return false;
return CA()(left.first, right.first);
}
};
std::vector<std::pair<std::string, int> > peopleAndAges;
peopleAndAges.push_back(std::pair<std::string, int>("Anne", 23));
peopleAndAges.push_back(std::pair<std::string, int>("Bob", 23));
peopleAndAges.push_back(std::pair<std::string, int>("Charlie", 23));
peopleAndAges.push_back(std::pair<std::string, int>("Douglas", 23));
std::sort(peopleAndAges.begin(), peopleAndAges.end(),
lessByPairSecond<std::string, int>());
I would suggest merging these two lists into a single list of structures. That way you can simply define operator < like dirkgently said.
Jerry Coffin answer was fully clear and correct.
A just have a related issue that may grant a good discussion to the topic... :)
I had to reorder the columns of a matrix object (lets say TMatrix< T >) based on the sorting of a vector (lets say sequence)... The TMatrix< T > class do not provide reference access to it's rows (thus I can not create a structure to reorder it...) but conveniently provides a method TMatrix< T >::swap(row1, row2)...
So that's the code:
TMatrix<double> matrix;
vector<double> sequence;
//
// 1st step: gets indexes of the matrix rows changes in order to sort by time
//
// note: sorter vector will have 'sorted vector elements' on 'first' and
// 'original indexes of vector elements' on 'second'...
//
const int n = int(sequence.size());
std::vector<std::pair<T, int>> sorter(n);
for(int i = 0; i < n; i++) {
std::pair<T, int> ae;
ae.first = sequence[i];
ae.second = i;
sorter[i] = ae;
}
std::sort(sorter.begin(), sorter.end());
//
// 2nd step: swap matrix rows based on sorter information
//
for(int i = 0; i < n; i++) {
// updates the the time vector
sequence[i] = sorter[i].first;
// check if the any row should swap
const int pivot = sorter[i].second;
if (i != pivot) {
//
// store the required swaps on stack
//
stack<std::pair<int, int>> swaps;
int source = pivot;
int destination = i;
while(destination != pivot) {
// store required swaps until final destination
// is equals to first source (pivot)
std::pair<int, int> ae;
ae.first = source;
ae.second = destination;
swaps.push(ae);
// retrieves the next requiret swap
source = destination;
for(int j = 0; j < n; j++) {
if (sorter[j].second == source)
destination = j;
break;
}
}
}
//
// final step: execute required swaps
//
while(!swaps.empty()) {
// pop the swap entry from the stack
std::pair<int, int> swap = swaps.top();
destination = swap.second;
swaps.pop();
// swap matrix coluns
matrix.swap(swap.first, destination);
// updates the sorter
sorter[destination].second = destination;
}
// updates sorter on pivot
sorter[pivot].second = pivot;
}
}
I belive that's still O(n log n) since every row that is not in place will swap just one time...
Have fun! :)