1

I am just beginning in C++, and I was wondering if there was a way to sort a 2D array by the second value in each array. I have not found any way to do in online, so I am asking here.

For example, you would start with:

int exampleArray[5][2] = {
    {4, 20},
    {1, 4},
    {7, 15},
    {8, 8},
    {8, 1}
};

and after sorting, the array would be

int exampleArray[5][2] = {
    {8, 1},
    {1, 4},
    {8, 8},
    {7, 15},
    {4, 20}
};

In Python, you could just sort it using exampleArray.sort(key = lambda element : element[1]), but I do not know how to do it using C++

CoderTang
  • 460
  • 5
  • 14
  • Related: https://stackoverflow.com/questions/5897319/how-to-use-stdsort-to-sort-an-array-in-c https://stackoverflow.com/questions/16894700/c-custom-compare-function-for-stdsort – SuperStormer Sep 03 '21 at 00:36
  • Counter question: What have you tried? You might only be a little wrong and we can sort that out in no time. – user4581301 Sep 03 '21 at 00:46
  • @user4581301 I have no idea how to even approach this. – CoderTang Sep 03 '21 at 00:51
  • 1
    Fair enough. Arrays in C++ are second-class citizens in C++ and are a LOT harder to deal with than you're used to coming in from Python where an array is closer in spirit to C++'s `std::vector` (and still not a great match). [Here's an answer that should help you get started](https://stackoverflow.com/questions/20931669/sort-a-2d-array-in-c-using-built-in-functionsor-any-other-method). You'll have to tweak the rules used in the lambda expression that's being passed to `std::qsort` because it is currently sorting based on column 1 with column 2 breaking ties. – user4581301 Sep 03 '21 at 00:57
  • @CoderTang *I have not found any way to do in online* -- Think [outside the box](https://stackoverflow.com/questions/46382252/sort-array-by-first-item-in-subarray-c/46382976#46382976). – PaulMcKenzie Sep 03 '21 at 01:07
  • I forgot something earlier. If you have a fixed-size array, consider using [`std::array`](https://en.cppreference.com/w/cpp/container/array). You get the extra smarts of a C++ library container, use of most of the fun container-manipulating toys (obviously you're missing out on the ones that let you change the size of the container), and the runtime overhead compiles down to practically nothing. – user4581301 Sep 03 '21 at 02:07

3 Answers3

3

The short answer is: don't do that. C++ inherited it's built-in array from C, and it simply isn't really a very good fit for what you're trying to do.

Something that's reasonably similar and easy to implement would be to use std::vector instead of arrays.

std::vector<std::vector<int>> someVector {
    {4, 20},
    {1, 4},
    {7, 15},
    {8, 8},
    {8, 1}
};

Sorting this based on the second item in each row is pretty trivial:

    std::sort(someVector.begin(), someVector.end(), 
        [](auto const &a, auto const &b) { return a[1] < b[1]; });

We can then print out the result to verify that it's working as expected:

for (auto const &row : someVector)
    std::cout << row[0] << "\t" << row[1] << "\n";

As you'd expect, this produces:

8   1
1   4
8   8
7   15
4   20
Jerry Coffin
  • 476,176
  • 80
  • 629
  • 1,111
0

You can use a struct to keep your data:

struct Data
{
    int x,y;
};
vector<Data> a;

using std::sort , you can use a lambda function to acheive your goal

std::sort(a.begin(),a.end(),[](Data e1,Data e2){return e1.y<e2.y;});

Charles chen
  • 131
  • 4
0

Using vector is much simpler, but assuming you can't use std::vector, here is an alternate way of "sorting", based on the answer given here:

#include <iostream>
#include <algorithm>

int main()
{
    int exampleArray[5][2] = {
        {4, 20},
        {1, 4},
        {7, 15},
        {8, 8},
        {8, 1}
    };

    // create the indexing (there are 5 2D entries)
    int index[] = {0,1,2,3,4};

    // sort the index based on the second value in the 2D array    
    std::sort(index, index + 5, [&](int n1, int n2) 
             { return exampleArray[n1][1] < exampleArray[n2][1]; });

    // output results
    for (int i = 0; i < 5; ++i)
       std::cout << exampleArray[index[i]][0] << " " << exampleArray[index[i]][1] << "\n";
}

Output:

8 1
1 4
8 8
7 15
4 20

Basically, you want to sort the index array based on the second value in the 2D array. That's what the lambda function is stating -- the index array is being "sorted", and not the original 2D array.

Once the sorting is finished, the index array is used to access the items in the 2D array in a sorted fashion.

From there, if you want the changes stored in the actual 2D array, you could rebuild the original array using the sorted index:

    // rebuild the original array using the sorted index
    int tempArray[5][2] = {};
    for (int i = 0; i < 5; ++i)
    {
        tempArray[i][0] = exampleArray[index[i]][0];
        tempArray[i][1] = exampleArray[index[i]][1];
    }
    
    // copy the new sorted array to the original array
    memcpy(exampleArray, tempArray, sizeof(exampleArray));
PaulMcKenzie
  • 34,698
  • 4
  • 24
  • 45