-1

Hi Im pretty new to C++ and programming. I am trying to make a function to transform a 2D-Vector to a 1D single Row vector. Unfortunately Im getting the Error: "expression must have pointer-to-object type" If I type the exact same code in the main function without specifying a function it works fine is seems just not to work if I want to create a function. Here is the code:

std::vector<float> onelinevector(std::vector<std::vector<float>> invector, int column){

int vsize = (int) invector.size() * column;
std::vector<float> v1d(vsize);
std::cout << "Creating 1D Vector:\n"<< "Inputvector Size: " << invector.size() << "Rows " << column << " Columns" << std::endl;
int k = 0;

for (int i = 0; i<invector.size(); i++) {

    for (int j = 0; j<column ; j++) {
      v1d[k] = invector[i][j];
      k++;
    }

}
return v1d;
}

This is the line that causes the error: v1d[k] = invector[i][j];

I hope you can help me with that.

LLSv2.0
  • 501
  • 6
  • 20
shyney
  • 67
  • 11
  • 1
    This expression is invalid: `invector[i][j]` because `invector[i]` returns a `float` and you may not call a `[]` operator on it. – vahancho Mar 12 '20 at 15:01
  • 1
    There's no 2D vector in your code? I assume `invector` should be a vector of vectors? – Emil Laine Mar 12 '20 at 15:02
  • @vahancho I still dont understand I want to iterate between every row and column of the input vector and assign it to the new single row vector v1d. thats why I use the indexes of the input vector and iterate through a for loop in a for loop the outer loop is for the rows and the inner loop is for the columns indexes. can you explain it for a noob? – shyney Mar 12 '20 at 15:10
  • @emlai the the invector should be the 2D Vector for example something like this : std::vector inputvector = { {1, 2, 3}, {4, 5, 6}, {7, 8, 9} }; – shyney Mar 12 '20 at 15:15

2 Answers2

1

If I type the exact same code in the main function without specifying a function it works fine

Nope. You would have exactly the same problem.

[...] the invector should be the 2D Vector [...]

It isn't. std::vector<float> invector is a vector of floats not a 2D vector of any kind.

You get the error, because invector[i] is a float and floats have no operator[].

Other minor issues in your code:

Don't pass big vectors by value. Pass by reference instead to avoid a unnecessary copy.

int vsize = (int) invector.size() * column;

Don't use c-style casts ((int)). If you want to cast use static_cast. Though you don't need to cast here at all. The type to use for container sizes is size_t. It is unsigned. int is signed, but a container size cannot be negative. Actually, don't pass column. Once you make invector 2D it knows its dimensions (see below), no need to pass that along with the vector.

Further, keeping track of the index k is error prone and not really necessary. The loops are easier when written as range based for loops.

Assuming all inner vectors are of same size, and minimal changes applied to your code, it could look like this:

using my1Dvector = std::vector<float>;
using my2Dvector = std::vector<my1Dvector>;
my1Dvector onelinevector(const my2Dvector& invector){
    my1Dvector v1d;
    if (invector.size() == 0) return v1d;
    v1d.reserve(invector.size() * invector.front().size());

    for (auto& innervector : invector) {
        for (auto& element : innervector) {
            v1d.push_back(element);
        }
    }
    return v1d;
}

Almost last but not least, instead of pushing the element manually, you can use insert (see here):

my1Dvector onelinevector(const my2Dvector& invector){
    my1Dvector v1d;
    if (invector.size() == 0) return v1d;
    v1d.reserve(invector.size() * invector.front().size());

    for (auto& innervector : invector) {
        v1d.insert(v1d.end(),innervector.begin(),innervector.end());
    }
    return v1d;
}

Last but not least, such transformation smells like doing unnecessary work. If you want the data stored in a flat vector, you better store it in a flat vector in the first place. On the other hand, you could keep it in the 2D vector and emulate 1D access by transforming the index only.

463035818_is_not_an_ai
  • 109,796
  • 11
  • 89
  • 185
1

If you want to convert a 2d vector in a 1d vector first of all you need to pass to your function a 2d vector. In your program you tried to add line by line than that make the things easier. You have several ways to do that like you can see below:

Important to note the '&' in the parameter. It indicate the vector is passed by reference. Without it you will copy the whole vector unnecessarily yo your function. Also I set it as const for correctness.

using namespace std;

vector<float> onelinevectorCStyle(const vector<vector<float>>& invector) {
    vector<float> OneD;

    for (vector<float>::size_type X = 0; X < invector.size(); ++X)
        for (vector<float>::size_type Y = 0; Y < invector[X].size(); ++Y)
                OneD.emplace_back(invector[X][Y]);

    return OneD;
}

vector<float> onelinevectorCPPIterator(const vector<vector<float>>& invector) {
    vector<float> OneD;

    for (auto X = invector.cbegin(); X != invector.cend(); ++X)
        for (auto Y = (*X).cbegin(); Y != (*X).cend(); ++Y)
            OneD.emplace_back(*Y);

    return OneD;
}

vector<float> onelinevectorElegantWay(const vector<vector<float>>& invector) {
    vector<float> OneD;

    for (auto& X : invector)
        for (auto& Y : X)
            OneD.emplace_back(Y);

    return OneD;
}
TheArchitect
  • 1,160
  • 4
  • 15
  • 26