HiveBrain v1.2.0
Get Started
← Back to all entries
patterncppMinor

Simple class for 2D <-> 1D array index conversion

Submitted by: @import:stackexchange-codereview··
0
Viewed 0 times
conversionsimplearrayforindexclass

Problem

I made a class to convert the index between 2D and 1D arrays.
For example,
between

{1,3,5,7,9,11} and {{1,3},{5,7},{9,11}}

  • When i is 0, xy should be (0,0)



  • When i is 1, xy should be (0,1)



  • When i is 2, xy should be (1,0)



And so on...

I would be able to convert between the i-index and the xy-index to find get the equivalent location. I feel like this piece of code may be too long for its purpose.

class IndexConv {
    public:
    IndexConv(int rows, int cols);
    bool check_i(int i) const;
    bool check_xy(int x, int y) const;
    pair to_xy(int i) const;
    int to_i(int x, int y) const;
    private:
    const int rows_;
    const int cols_;
};

IndexConv::IndexConv(int rows, int cols)
    :rows_(rows), cols_(cols) {}

bool IndexConv::check_i(int i) const
{
    return i>=0 || i=0 && y>=0 && x IndexConv::to_xy(int i) const
{
    if(!check_i(i)) throw out_of_range("IndexConv: i out of bounds.");
    int x = i/cols_;
    int y = i-x*cols_;
    return make_pair(x,y);
}

int IndexConv::to_i(int x, int y) const
{
    if(!check_xy(x,y)) throw out_of_range("IndexConv: xy out of bounds.");
    int i = x*cols_+ y;
    return  i;
}

Solution

Use modulus

Instead if this i-x*cols_ you can use the modulus operator i % cols_.

Use a unsigned type.

If you use unsigned there is no need to check for x >= 0 && y >= 0. Also you can con throw the exception directly in check. And you just need check_xy.

void IndexConv::check(unsigned x, unsigned y) const
    {
        if(x >= rows_ || y >= cols_) 
            throw std::out_of_range("IndexConv: parameter out of bounds.");
    }

    pair IndexConv::to_xy(unsigned i) const
    {
        int x = i / cols_;
        int y = i % cols_;
        check(x, y);
        return make_pair(x, y);
    }

    int IndexConv::to_i(unsigned x, unsigned y) const
    {
        check(x, y);
        return x * cols_ + y;
    }


EDIT: Changed the answer to keep check_xy. Keeping check_i can map (0,2) to 2 when it should throw an exception (Following your example).

Code Snippets

void IndexConv::check(unsigned x, unsigned y) const
    {
        if(x >= rows_ || y >= cols_) 
            throw std::out_of_range("IndexConv: parameter out of bounds.");
    }

    pair<int, int> IndexConv::to_xy(unsigned i) const
    {
        int x = i / cols_;
        int y = i % cols_;
        check(x, y);
        return make_pair(x, y);
    }

    int IndexConv::to_i(unsigned x, unsigned y) const
    {
        check(x, y);
        return x * cols_ + y;
    }

Context

StackExchange Code Review Q#120827, answer score: 5

Revisions (0)

No revisions yet.