Getting Value from particular index in 2d vector in c++ - 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];
}

Related

Suppose we have two std::vectors v1 and v2 and we dont want to combine these in a struct. How to transform v2 the same way v1 was transformed by sort?

This is a followup of this question. The only difference is the constrain that the two vectors cannot be combined in a struct.
Suppose we have a vector
std::vector<double> v1 = {9.0,5.0,3.0,2.0,1.0};
Now we sort the vector v1. Let v2 be given by
std::vector<std::string> v2 = {"you?","are","how","there","hello"};
How to transform v2 the same way v1 was transformed by sort?
Based on this answer, you can use an array of indices to "sort" the vector of doubles, and just use the resulting index array to index the vector of strings.
#include <algorithm>
#include <iostream>
#include <string>
#include <numeric>
int main()
{
std::vector<double> v1 = {5.0,9.0,3.0,2.0,1.0};
std::vector<std::string> v2 = {"are", "you?","how","there","hello"};
// Create an array of indices, starting from 0
std::vector<int> index(v1.size());
std::iota(index.begin(), index.end(), 0);
// "Sort" the index array according to the value in the vector of doubles
std::sort(index.begin(), index.end(),
[&](int n1, int n2){ return v1[n1] < v1[n2]; });
// Output results
for (auto i : index )
std::cout << v2[i] << " " << v1[i] << ", index is " << i << "\n";
}
Output:
hello 1, index is 4
there 2, index is 3
how 3, index is 2
are 5, index is 0
you? 9, index is 1
Note:
I changed the original data to illustrate how the index array works.
The abstraction you are missing is the ability to view the vectors as one item. That's the role that a vector of indices is a proxy for in another answer.
I think it is worth mentioning that there are libraries that provide such a concept (often under the name "zip"). For example, with range-v3:
std::vector<double> v1 = {5, 9, 3, 2, 1};
std::vector<std::string> v2 = {"are", "you?", "how", "there", "hello"};
// Sort the vectors
ranges::actions::sort(ranges::views::zip(v1, v2));
// Output results
for (std::size_t i = 0; i < v1.size(); ++i)
std::cout << v2[i] << " " << v1[i] << ", index is " << i << "\n";
A possible solution uses a helper std::vector<int>:
#include <iostream>
#include <vector>
#include <algorithm>
#include <stdexcept>
template<typename T>
void MySort(std::vector<T> t, std::vector<int>& helper)
{
struct StructHelper
{
T t1;
int num;
StructHelper(T t, int i): t1{t}, num{i} {};
bool operator<(const StructHelper& other) const
{ return t1 < other.t1; }
};
std::vector<StructHelper> shVector;
for(int i=0; i<t.size(); ++i)
{
shVector.emplace_back(t[i], i);
}
std::sort(shVector.begin(), shVector.end());
helper = std::vector<int>(t.size());
for(int i=0; i<t.size(); ++i)
{
helper[i] = shVector[i].num;
}
}
template<typename T>
void MySortUsingHelper(std::vector<T>& t1, const std::vector<int>& helper)
{
if(t1.size() != helper.size()) throw std::out_of_range("not same size");
std::vector<T> t2(t1.size());
for(int i=0; i<helper.size(); ++i)
{
t2[i] = t1[helper[i]];
}
t1 = t2;
}
int main() {
std::vector<double> v1 = {9.0,5.0,3.0,2.0,1.0};
std::vector<int> helper;
MySort(v1, helper);
std::vector<std::string> v2 = {"you?","are","how","there","hello"};
MySortUsingHelper(v2, helper);
for(auto elem : v2)
{
std::cout << elem << " ";
}
return 0;
}
You can run the above code online to see the following output:
hello there how are you?

how to shift elements of array from one column to another column by using pointer in c++

how to shift elements of array from one column to another column by using pointer to pointer in c++
When I do this, it says "Reference to non-static member function must be called"
for (int i = 0; i < size; i++)
{
array[n]->my_data[i] = array[n]->my_arr[i+1];
}
Here are a couple of C++ ways to do it. The second one, using std::rotate, is to be preferred.
#include <algorithm>
#include <vector>
#include <iostream>
void show(const std::vector<int> & vec) {
for (auto v : vec) {
std::cout << v << " ";
}
std::cout << '\n';
}
int main() {
std::vector<int> vec{ 0,1,2,3,4,5,6,7,8,9 };
// Re-invent wheel
for (auto it = vec.begin() + 1; it != vec.end(); ++it) {
*(it - 1) = std::move(*it);
}
vec.pop_back();
show(vec);
// No wheel re-invention
std::rotate(vec.begin(), vec.begin() + 1, vec.end());
vec.pop_back();
show(vec);
}
If you want to use a fixed size array on the stack, this is the way. Do not use
array int[10];
#include <algorithm>
#include <array>
#include <string>
#include <iostream>
const int sz = 5;
void show(const std::array<std::string, sz> & vec) {
for (auto v : vec) {
std::cout << v << " ";
}
std::cout << '\n';
}
int main() {
std::array<std::string, sz> vec{ "zero", "one", "two", "three", "four" };
// Roll your own
for (auto it = vec.begin() + 1; it != vec.end(); ++it) {
std::swap(*(it - 1), *it);
}
show(vec);
// No wheel re-invention
std::rotate(vec.begin(), vec.begin() + 1, vec.end());
show(vec);
}
It should go without saying that the C++ way is not to use fixed arrays at all. You should prefer STL vector over fixed arrays whenever possible. That being said, this might have been an introductory assignment where you must re-invent the wheel so to speak. I’m assuming you are constrained to fixed arrays for whatever reason. If not, get rid of them!
You didn't specify what array[n] is or what what the size of my_data is, or what even my_data holds. I'm going to answer this assuming that my_data contains a bunch of integers and that you wanted to rotate every element in that array to the left by 1 "column", making the first element the new last. Here's how you could do it. You need to take care to not overrun your array length.
const size_t len{10};
int my_data[len] = {0,1,2,3,4,5,6,7,8,9};
int i, temp;
temp = my_data[0]; ///< temp copy of data at 0
for (i = 0; i != len-1; i++)
{
my_data[i] = my_data[i+1]; ///< shift left by 1
}
my_data[i] = temp; ///< old data at 0 goes to the new end
Input:
0 1 2 3 4 5 6 7 8 9
Output:
1 2 3 4 5 6 7 8 9 0

How to initialize 2D array to false using ranged-based for loop

I am currently stuck trying to use a range base for loop to initialize my array.
What i have currently does it but its not utilizing C++ 11 Array in the constructor. The constructor is void and takes no parameters
//sets everything to flase
for (size_t rowCount = 0; rowCount < NROWS; ++rowCount) {
for (size_t colCount = 0; colCount < NCOLS; ++colCount){
m_Floor[rowCount][colCount] = STARTING_PEN_POSITION;
}
}
Here is what I have so far to set everything to false (starting pen position)
for (auto const &row : m_Floor) {
for (auto const &column : row) {
//something = STARTING_PEN_POSITION;
}
}
and this array is inside the header file
std::array <std::array <bool, NCOLS>, NROWS> m_Floor;
where NCOLS is a constant static of size_t with a value of 70
and NROWS is a constant static of size_t with a value of 22
I am not very clear on the meaning of your question so I will post the answers to the two possible questions I can see above. The first being why your intialization in a range based for loop is not working. As pointed out in the comments, you need to remove the const. Reference the following compilable program for that
#include <iostream>
#include <array>
using std::array;
using std::cout;
using std::endl;
int main() {
array<array<int, 10>, 10> two_dimensional_array;
for (auto& arr : two_dimensional_array) {
for (auto& ele : arr) {
ele = 0;
}
}
// print all the values
for (auto arr : two_dimensional_array) {
for (auto ele : arr) {
cout << ele << " ";
}
cout << endl;
}
return 0;
}
The other question I inferred is that you want a nice way to initialize your 2 dimensional array in one line in the constructor. You can achieve this with vectors. They are dynamic arrays which are usually super optimized. You can use the vector constructor to initialize objects. Reference the following code
#include <iostream>
#include <vector>
using std::cout;
using std::endl;
using std::vector;
int main() {
vector<vector<int>> two_dimensional_vector (10, vector<int> (10, 5));
for (auto& vec : two_dimensional_vector) {
for (auto ele : vec) {
cout << ele << " ";
}
cout << endl;
}
return 0;
}
Note that I have not used the uniform initialization syntax because this is one of the places where it can be confusing

how can I find repeated elements in a vector [duplicate]

This question already has answers here:
Checking for duplicates in a vector [duplicate]
(5 answers)
Closed 9 years ago.
I have a vector of int which can include maximum 4 elements and minimum 2, for example :
std::vector<int> vectorDATA(X); // x means unknown here
What I want to do is to erase the elements that are repeated for example :
vectorDATA{1,2,2} to vectorDATA{1,2}
vectorDATA{1,2,3} to nothing changes
vectorDATA{2,2,2} to vectorDATA{2}
vectorDATA{3,2,1,3} to vectorDATA{3,2,1}
vectorDATA{1,2,1,2} to vector{1,2}
and so on
here a code simple :
cv::HoughLines(canny,lineQ,1,CV_PI/180,200);
std::cout << " line Size "<<lineQ.size()<< std::endl;
std::vector<int> linesData(lineQ.size());
std::vector<int> ::iterator it;
if(lineQ.size() <=4 && lineQ.size() !=0 ){
if(lineQ.size()==1){
break;
}else {
for ( int i = 0; i<lineQ.size();i++){
linesData[i] = lineQ[i][1]; // my comparison parameter is the lineQ[i][1]
}
// based on the answer I got I'm trying this but I really don't how to continue ?
std::sort(lineQ.begin(),lineQ.end(),[](const cv::Vec2f &a,const cv::Vec2f &b)
{
return ????
}
I tried use a for and do while loop, but I didn't get it, and the function std::adjacent_find this has a condition that the elements should be consecutive.
Maybe it's easy but I just don't get it !
thanks for any help !
The easy way is sort then unique-erase, but this changes order.
The c++11 order preserving way is to create an unordered_set<int> s; and do:
unordered_set<int> s;
vec.erase(
std::remove_if( vec.begin(),vec.end(), // remove from vector
[&](int x)->bool{
return !std::get<1>(s.insert(x)); // true iff the item was already in the set
}
),
vec.end() // erase from the end of kept elements to the end of the `vec`
);
which is the remove-erase idiom using the unordered_set to detect duplicates.
I didn't see a sort-less source code in the already mentioned answers, so here it goes. Hash table for checking duplicates, shifting unique elements towards the front of the vector, note that src is always >= dst and dst is the number of copied, i.e. unique elements at the end.
#include <unordered_set>
#include <vector>
#include <iostream>
void
uniq (std::vector<int> &a) {
std::unordered_set<int> s;
size_t dst = 0;
for (size_t src = 0; src < a.size(); ++src) {
if (s.count (a[src]) == 0) {
s.insert (a[src]);
a[dst++] = a[src];
}
}
a.resize (dst);
}
int
main () {
std::vector<int> a = { 3, 2, 1, 3, 2, 1, 2, 3, 4, 5 ,2, 3, 1, 1 };
uniq (a);
for (auto v : a)
std::cout<< v << " ";
std::cout << std::endl;
}
If you want to realy remove repeated elements, you may try something like this:
#include <iostream>
#include <algorithm>
#include <vector>
using namespace std;
int main () {
int data[] = {1,2,3,2,1};
vector<int> vectorDATA = (&data[0], &data[0] + 5);
sort(vectorDATA.begin(),vectorDATA.end());
for(int i = 0; i < vectorDATA.size()-1; ++i)
{
if(vectorDATA[i] == vectorDATA[i+1])
vectorDATA.erase(vectorDATA.begin()+i+1);
}
for(int i = 0; i < vectorDATA.size();++i)
{
cout << vectorDATA[i] << " ";
}
cout << endl;
return 0;
}
Lack of of this method is then elements lost his order.

Creating a new C++ subvector?

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;
}
~