Creating a new C++ subvector? - c++

Say I have a vector with values [1,2,3,4,5,6,7,8,9,10]. I want to create a new vector that refers to, for example, [5,6,7,8]. I imagine this is just a matter of creating a vector with pointers or do I have to push_back all the intermediary values I need?

One of std::vector's constructor accepts a range:
std::vector<int> v;
// Populate v.
for (int i = 1; i <= 10; i++) v.push_back(i);
// Construct v1 from subrange in v.
std::vector<int> v1(v.begin() + 4, v.end() - 2);

This is fairly easy to do with std::valarray instead of a vector:
#include <valarray>
#include <iostream>
#include <iterator>
#include <algorithm>
int main() {
const std::valarray<int> arr={0,1,2,3,4,5,6,7,8,9,10};
const std::valarray<int>& slice = arr[std::slice(5, // start pos
4, // size
1 // stride
)];
}
Which takes a "slice" of the valarray, more generically than a vector.
For a vector you can do it with the constructor that takes two iterators though:
const std::vector<int> arr={0,1,2,3,4,5,6,7,8,9,10};
std::vector<int> slice(arr.begin()+5, arr.begin()+9);

You don't have to use push_back if you don't want to, you can use std::copy:
std::vector<int> subvector;
copy ( v1.begin() + 4, v1.begin() + 8, std::back_inserter(subvector) );

I would do the following:
#include <vector>
#include <iostream>
using namespace std;
void printvec(vector<int>& v){
for(int i = 0;i < v.size();i++){
cout << v[i] << " ";
}
cout << endl;
}
int main(){
vector<int> v;
for(int i = 1;i <= 10;i++) v.push_back(i);
printvec(v);
vector<int> v2(v.begin()+4, v.end()-2);
printvec(v2);
return 0;
}
~

Related

Select all elements but one with given index from std::vector?

Given a std::vector, for example of ints
std::vector vec{10, 20, 30}
how to select all items except of with given index, for example int i=1 resulting
std::vector {10, 30}?
If you just want to "select" values from the original vector, I would create another vector with all the new values.
#include <iostream>
#include <vector>
using namespace std;
int main() {
vector<int> vect{ 10, 20, 30 };
vector<int> selected;
int i = 1;
for (int j = 0; j < vect.size(); j++) {
if (j != i) {
selected.push_back(vect[j]);
}
}
// Added so you can check the new values
for (int z = 0; z < selected.size(); z++) {
cout << selected[z] << " ";
}
return 0;
}
However, if you want to erase values from your original vector I would recommend using the vector.erase method (research the documentation).
Here is a function for it where you can pass the vector and index and it will return you the new vector without that index element.
#include <iostream>
#include <vector>
using namespace std;
// returns a new vector without the v[index]
vector<int> getElementsExceptIndex(vector<int> v, int index){
vector<int> newVector;
for(auto &x:v ){
if(( &x - &v[0]) != index)
newVector.push_back(x);
}
return newVector;
}
int main() {
vector<int> originalVector{ 10, 20, 30 ,33,53};
int index=1;
auto RemovedIndexVector = getElementsExceptIndex(originalVector,index);
for(auto item:RemovedIndexVector)
cout<<item<<" ";
return 0;
}
// Output - 10 30 33 53
Hope this helps

How can I erase all items from a vector? C++

I am just trying to make all my elements 0 without doing it manually with
for (i = 1; i <= n; i++)
v[i] = 0;
I found online that i can use this command: v.clear(); but it doesn't work:
error: request for member 'clear' in 'v', which is of non-class type 'int [101]'
Here's my code:
#include <iostream>
#include <algorithm>
#include <vector>
using namespace std;
int n,i,v[101];
int main() {
cin>>n;
for(i=1;i<=n;i++)
cin>>v[i];
v.clear();
for(i=1;i<=n;i++)
cout<<v[i]<<" ";
return 0;
}
We have std::fill, that can be used with C-style arrays, too:
std::fill(std::begin(v), std::end(v), 0);
You have an array. Arrays in C++ do not have methods. What you need is to call the standard C function memset.
For example
#include <cstring>
//...
std::memset( v, 0, n * sizeof( int ) );
Also indices for arrays in C++ start from 0. So use for loops like
for( i = 0; i < n; i++ )
Maybe, you can use std::array , it can also specify the size like int v[101] .
Then, you can use v = {0} to make make all my elements 0.
For example:
#include <iostream>
#include <array>
using namespace std;
int main() {
array<int, 101> v;
for (auto &elem : v)
cin >> elem;
v = {0};
for (auto elem : v)
cout << elem << " ";
}
If you don't like std::array, you can also do like the following.
int v[5] = {1, 2, 3, 4, 5};
int *p = v;
while (*p++ = 0, *p != 0) { };
In fact, I think that std::fill(std::begin(v), std::end(v), 0); that user Evg answered is best.

How to Subtract the first element in a vector from another first element in another vector?

I have 2 vectors of ints.
say the first one has (2,1).
and the second one (1,1).
I am trying to subtract numbers like this:
2 - 1,
1 - 1
then I need to add these 2 numbers so the final answer would be 1.
I've tried a for loop, but it's subtracting each number from each element, instead of only the first one.
This is what I've tried so far.
vector<int> temp;
for(unsigned i =0; i < Vec1.size(); i++)
for(unsigned o =0; o < Vec2.size(); o++)
temp.push_back(Vec1.at(i).nums- Vec2.at(o).nums);
//where nums, are just the numbers showed above
The output as you would expect is :
1
1
0
0
and I need it to be:
1
0
then I can just do a for loop to add all the ints together.
Any help, would be greatly appreciated!
I've tried a for loop, but it's subtracting each number from each element, instead of only the first one.
You are not doing it the right way. You have been using cascaded for loops and hence, you are subtracting each element of first vector from each element of second vector.
There are two ways to correctly implement:
One involves writing your own functions to subtract two vector and then adding elements of the result.
#include <iostream>
#include <vector>
std::vector<int> subtract(const std::vector<int>& a, const std::vector<int>& b)
{
std::vector<int> result;
const int SIZE = std::min(a.size(), b.size());
for (int i = 0; i < SIZE; i++)
result.push_back(a[i] - b[i]);
return result;
}
int addAllElements(const std::vector<int>& a)
{
int result = 0;
for (auto i: a)
result += i;
return result;
}
int main(void)
{
std::vector<int> a = {2, 1};
std::vector<int> b = {1, 1};
std::cout << "Result is " << addAllElements(subtract(a, b)) << std::endl;
return 0;
}
The other method (preferred) involves using STL:
#include <iostream>
#include <vector>
#include <algorithm>
#include <numeric>
int main(void)
{
std::vector<int> a = { 2, 1 };
std::vector<int> b = { 1, 1 };
std::vector<int> result;
std::transform(std::begin(a), std::end(a), std::begin(b), std::back_inserter(result), [](const auto a, const auto b)
{
return a - b;
}
);
int sumAllElements = std::accumulate(result.begin(), result.end(), 0);
std::cout << "Result is " << sumAllElements << std::endl;
return 0;
}
The above code uses lambda expression. To know more about them, see this link.
std::accumulate sums all the elements of the container and std::transform performs the transformation (specified in it's fifth argument) on two vectors and put the result in a different vector. We have used lambda expression to perform the required sub operation.
EDIT:
To implement it without lambda is also easy. You can use function pointers.
#include <iostream>
#include <vector>
#include <algorithm>
#include <numeric>
double subtract(const double a, const double b)
{
return a - b;
}
int main(void)
{
std::vector<int> a = { 2, 1 };
std::vector<int> b = { 1, 1 };
std::vector<int> result;
std::transform(std::begin(a), std::end(a), std::begin(b), std::back_inserter(result), subtract);
int sumAllElements = std::accumulate(result.begin(), result.end(), 0);
std::cout << "Result is " << sumAllElements << std::endl;
return 0;
}
There are various advantages of using lambda expression.
NOTE:
You can also use std::minus instead of defining you own function. Like this:
std::transform(std::begin(a), std::end(a), std::begin(b), std::back_inserter(result), std::minus<int>());
In C++17, you can combine std::transform and std::reduce/std::accumulate calls with std::transform_reduce:
const std::vector<int> vec1 {2, 1};
const std::vector<int> vec2 {1, 1};
auto res = std::transform_reduce(vec1.begin(), vec1.end(),
vec2.begin(),
0,
std::plus<>(),
std::minus<>());
Demo
Here is an example using the STL:
#include <algorithm>
#include <iostream>
#include <numeric>
#include <vector>
int main() {
std::vector<int> vec1 {2, 1};
std::vector<int> vec2 {1, 1};
std::vector<int> temp;
std::transform(begin(vec1), std::end(vec1), std::begin(vec2),
std::back_inserter(temp), [](const auto a, const auto b) {return a - b;});
auto sum = std::accumulate(temp.begin(), temp.end(), 0);
std::cout << "Result: " << sum << "\n";
return 0;
}

Getting Value from particular index in 2d vector in c++

I have made a 2d vector using :
std::vector<std::vector<int> *> hp;
I want to initialise hp vector and get the data from particular index for the same.
for eg,
Getting the values from hp[2][2];
Please do help
Try the following
#include <iostream>
#include <vector>
int main()
{
std::vector<std::vector<int> *> hp =
{
new std::vector<int> { 1, 2, 3 },
new std::vector<int> { 4, 5, 6 }
};
for ( std::vector<std::vector<int> *>::size_type i = 0;
i < hp.size(); i++ )
{
for ( std::vector<int>::size_type j = 0; j < hp[i]->size(); j++ )
{
std::cout << ( *hp[i] )[j] << ' ';
// std::cout << hp[i]->operator[]( j ) << ' ';
}
std::cout << std::endl;
}
for ( auto &v : hp ) delete v;
return 0;
}
For commented and uncommented statements within the inner loop the program output will be the same and look like
1 2 3
4 5 6
Note that
std::vector<std::vector<int>*> hp
defines a std::vector containing pointers to objects of type
std::vector<int>
As ravi mentioned, you probably want
std::vector<std::vector<int>> hp;
But if you insist on having a vector with pointers,
std::vector<std::vector<int>*> hp;
(*hp[2])[2] // retrieves third value from third std::vector<int>
Remark: In C++11 (also called C++0x) you don't need the spacing between the ">" (as I wrote in the examples).
If these are pointers to vectors that are owned elsewhere:
#include <vector>
#include <iostream>
#include <algorithm>
int main() {
// Create owning vector
std::vector<std::vector<int>> h = {{0,1,2},{3,4,5},{6,7,8}};
// Create vector of pointers
std::vector<std::vector<int>*> hp(h.size());
//auto get_pointer = [](std::vector<int>& v){return &v;}; // C++11
auto get_pointer = [](auto& v){return &v;}; // C++14
std::transform(h.begin(), h.end(), hp.begin(), get_pointer);
// Output value in third column of third row
std::cout << (*hp[2])[2];
}

boost zip_iterator and std::sort

I have two arrays values and keys both of the same length.
I want to sort-by-key the values array using the keys array as keys.
I have been told the boost's zip iterator is just the right tool for locking two arrays together and doing stuff to them at the same time.
Here is my attempt at using the boost::zip_iterator to solve sorting problem which fails to compile with gcc. Can someone help me fix this code?
The problem lies in the line
std::sort ( boost::make_zip_iterator( keys, values ), boost::make_zip_iterator( keys+N , values+N ));
#include <iostream>
#include <iomanip>
#include <cstdlib>
#include <ctime>
#include <vector>
#include <algorithm>
#include <boost/iterator/zip_iterator.hpp>
#include <boost/tuple/tuple.hpp>
#include <boost/tuple/tuple_comparison.hpp>
int main(int argc, char *argv[])
{
int N=10;
int keys[N];
double values[N];
int M=100;
//Create the vectors.
for (int i = 0; i < N; ++i)
{
keys[i] = rand()%M;
values[i] = 1.0*rand()/RAND_MAX;
}
//Now we use the boost zip iterator to zip the two vectors and sort them "simulatneously"
//I want to sort-by-key the keys and values arrays
std::sort ( boost::make_zip_iterator( keys, values ),
boost::make_zip_iterator( keys+N , values+N )
);
//The values array and the corresponding keys in ascending order.
for (int i = 0; i < N; ++i)
{
std::cout << keys[i] << "\t" << values[i] << std::endl;
}
return 0;
}
NOTE:Error message on compilation
g++ -g -Wall boost_test.cpp
boost_test.cpp: In function ‘int main(int, char**)’:
boost_test.cpp:37:56: error: no matching function for call to ‘make_zip_iterator(int [(((unsigned int)(((int)N) + -0x00000000000000001)) + 1)], double [(((unsigned int)(((int)N) + -0x00000000000000001)) + 1)])’
boost_test.cpp:38:64: error: no matching function for call to ‘make_zip_iterator(int*, double*)’
You can't sort a pair of zip_iterators.
Firstly, make_zip_iterator takes a tuple of iterators as input, so you could call:
boost::make_zip_iterator(boost::make_tuple( ... ))
but that won't compile either, because keys and keys+N doesn't have the same type. We need to force keys to become a pointer:
std::sort(boost::make_zip_iterator(boost::make_tuple(+keys, +values)),
boost::make_zip_iterator(boost::make_tuple(keys+N, values+N)));
this will compile, but the sorted result is still wrong, because a zip_iterator only models a Readable iterator, but std::sort also needs the input to be Writable as described here, so you can't sort using zip_iterator.
A very good discussion of this problem can be found here: https://web.archive.org/web/20120422174751/http://www.stanford.edu/~dgleich/notebook/2006/03/sorting_two_arrays_simultaneou.html
Here's a possible duplicate of this question: Sorting zipped (locked) containers in C++ using boost or the STL
The approach in the link above uses std::sort, and no extra space. It doesn't employ boost::zip_iterator, just boost tuples and the boost iterator facade. Std::tuples should also work if you have an up to date compiler.
If you are happy to have one extra vector (of size_t elements), then the following approach will work in ~ o(n log n) time average case. It's fairly simple, but there will be better approaches out there if you search for them.
#include <vector>
#include <iostream>
#include <algorithm>
#include <iterator>
using namespace std;
template <typename T1, typename T2>
void sortByPerm(vector<T1>& list1, vector<T2>& list2) {
const auto len = list1.size();
if (!len || len != list2.size()) throw;
// create permutation vector
vector<size_t> perms;
for (size_t i = 0; i < len; i++) perms.push_back(i);
sort(perms.begin(), perms.end(), [&](T1 a, T1 b){ return list1[a] < list1[b]; });
// order input vectors by permutation
for (size_t i = 0; i < len - 1; i++) {
swap(list1[i], list1[perms[i]]);
swap(list2[i], list2[perms[i]]);
// adjust permutation vector if required
if (i < perms[i]) {
auto d = distance(perms.begin(), find(perms.begin() + i, perms.end(), i));
swap(perms[i], perms[d]);
}
}
}
int main() {
vector<int> ints = {32, 12, 40, 8, 9, 15};
vector<double> doubles = {55.1, 33.3, 66.1, 11.1, 22.1, 44.1};
sortByPerm(ints, doubles);
copy(ints.begin(), ints.end(), ostream_iterator<int>(cout, " ")); cout << endl;
copy(doubles.begin(), doubles.end(), ostream_iterator<double>(cout, " ")); cout << endl;
}
After seeing another of your comments in another answer.
I though I would enlighten you to the std::map. This is a key value container, that preserves key order. (it is basically a binary tree, usually red black tree, but that isn't important).
size_t elements=10;
std::map<int, double> map_;
for (size_t i = 0; i < 10; ++i)
{
map_[rand()%M]=1.0*rand()/RAND_MAX;
}
//for every element in map, if you have C++11 this can be much cleaner
for (std::map<int,double>::const_iterator it=map_.begin();
it!=map_.end(); ++it)
{
std::cout << it->first << "\t" << it->second << std::endl;
}
untested, but any error should be simple syntax errors
boost::make_zip_iterator take a boost::tuple.
#include <boost/iterator/zip_iterator.hpp>
#include <boost/tuple/tuple.hpp>
#include <boost/tuple/tuple_comparison.hpp>
#include <iostream>
#include <iomanip>
#include <cstdlib>
#include <ctime>
#include <vector>
#include <algorithm>
int main(int argc, char *argv[])
{
std::vector<int> keys(10); //lets not waste time with arrays
std::vector<double> values(10);
const int M=100;
//Create the vectors.
for (size_t i = 0; i < values.size(); ++i)
{
keys[i] = rand()%M;
values[i] = 1.0*rand()/RAND_MAX;
}
//Now we use the boost zip iterator to zip the two vectors and sort them "simulatneously"
//I want to sort-by-key the keys and values arrays
std::sort ( boost::make_zip_iterator(
boost::make_tuple(keys.begin(), values.begin())),
boost::make_zip_iterator(
boost::make_tuple(keys.end(), values.end()))
);
//The values array and the corresponding keys in ascending order.
for (size_t i = 0; i < values.size(); ++i)
{
std::cout << keys[i] << "\t" << values[i] << std::endl;
}
return 0;
}