Problem with sorting with the iterator.

Jun 4, 2019 at 1:06am
The code I provided finds the largest value of each row in my matrice, and saves it along with its index.
What I want it to do is find the largest values in the WHOLE matrice, and save them along with their indexes, the ammoung of values I want is equal to the ammount of rows the matrice has, so if the matrice has 4 rows, I would want the 4 largest values of the while matrice, and save them along with their indexes.
This is my desired output:
The 0 largest 88.05 and index (2)(1)

The 1 largest 15.05 and index (1)(0)

The 2 largest 11.05 and index (2)(0)

The 3 largest 8.58 and index (1)(3)


This is the output im currently getting


The 0 largest 8.58 and index 3

The 1 largest 15.05 and index 0

The 2 largest 88.05 and index 1

The 3 largest -8.05 and index 1


include <iostream>
include <vector>
include <cstddef>
include <algorithm>
include <iterator>

int main()

{

std::vector<std::vector<double>> matrice {

{1.05, -8.05, 1.0, 8.58, 3.04},

{15.05, 8.05, 7.05, 8.58},

{11.05, 88.05, 7.06},

{-12.05, -8.05}

};

std::vector<std::pair<std::size_t, double>> indexLargestVec;

indexLargestVec.reserve(matrice.size());

for (const std::vector<double>& row : matrice) {

const auto iter = std::max_element(row.cbegin(), row.cend());

indexLargestVec.emplace_back(std::distance(row.cbegin(), iter), *iter);

}

std::size_t row = 0;

for(const std::pair < std::size_t, double>& indexElement: indexLargestVec)

std::cout << "The"<< row++ <<" largest of " << row++

<< indexElement.second

<< " and index " << indexElement.first << '\n';

return 0;

}
Jun 4, 2019 at 2:13am
Well, there are a few ways to do this, but one approach may be to change the std::pair as you're using it now to

 
...std::pair<double, std::size_t>...


This puts the sort key first in the pair, and now you can use the std::sort algorithm easily. This puts the vector in the reverse order that you require, but then you could simply traverse it in the reverse order, perhaps with a reverse iterator.

An alternative is to leave the pair as you have it, but provide a custom comparison function object to std::sort, to sort by the second entry of the pair in reverse order.
Last edited on Jun 4, 2019 at 2:14am
Jun 4, 2019 at 2:21am
Hey! Thanks for the reply, could you please exemplify?
Jun 4, 2019 at 2:25am
Which version do you prefer, the simpler one that you have iterate through in reverse, or the custom sort function object version that prints out just like you're doing now?
Jun 4, 2019 at 2:29am
The way I'm doing now if its not too much of a hassle, I actually thought it was fixable without too much trouble... damn.
Jun 4, 2019 at 2:53am
Hehehe....trouble.....that's funny....

Sorry, I couldn't resist...I've been working with PhysX source, planning to provide an OpenCL implementation as an option to their CUDA implementation so non-NVidia GPU's can also process physics, and working on a robotics simulation for a club (I volunteer to teach programming to the high school club)...now THAT'S trouble.....heheh

ok

A function object for comparison is just a class with a function operator overload that returns a bool and accepts the two const & parameters to be compared.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71

// I just like shorter types, so I typedef
// but choose a name you prefer

typedef std::pair< std::size_t, double >  RowVal; 

// this is a comparison function object to be used by std::sort

struct Comparator // call this what you like
{
 // in case you're not accustomed to typedefs, remember RowVal is the same as your std::pair

 // this is what sort expects, an overload of the function operator (), it's what makes this struct a function object

 bool operator ()(  const RowVal & rv1, const RowVal & rv2 )
   {
    // note: this is object traditionally answers "is less than"
    // but we want this reversed, so we answer what we prefer for 
    // a reverse sort

    return ( get<1>( rv1 ) > get<1>( rv2 ) );
   }
};


int main()
{

 std::vector<std::vector<double>> matrice 
   {
     {1.05, -8.05, 1.0, 8.58, 3.04},
     {15.05, 8.05, 7.05, 8.58},
     {11.05, 88.05, 7.06},
     {-12.05, -8.05}
   };
 

typedef std::vector< RowVal >  RowVec;

// even though this says RowVec, it's a typedef of exactly what
// you wrote before, so nothing has changed here
RowVec indexLargestVec;

indexLargestVec.reserve(matrice.size());

for (const std::vector<double>& row : matrice) 
  {
   const auto iter = std::max_element(row.cbegin(), row.cend());
   
   indexLargestVec.emplace_back(std::distance(row.cbegin(), iter), *iter);
  }


std::sort( indexLargestVec.begin(), indexLargestVec.end(), Comparator() );


std::size_t row = 0;

for(const std::pair < std::size_t, double>& indexElement: indexLargestVec)

std::cout << "The "<< row++ <<" largest of " << row++ << " "

<< indexElement.second

<< " and index " << indexElement.first << '\n';

return 0;
}






There is one thing I have not bothered to deal with....in your loop you label with "row++", but that doesn't move around by sorting. It may be that you need more than just a std::pair, but a struct that holds the related elements you require to be sorted...that I have no idea from here.
Last edited on Jun 4, 2019 at 2:59am
Jun 4, 2019 at 4:49am
1
2
3
4
5
6
7
8
9
10
#include <iostream>
#include <utility>
using namespace std;
 
int main(){
	double arr[4][3]={{1.2,5.6,9.1},{0.3,8.9,2.4},{1.3,6.2,2.7},{2.3,5.2,4.0}};
	pair<int,int> p[4]; //indexes of max value of each row
	p[0] = make_pair(0,2); //index of max value of row_0	
	cout<< arr[p[0].first][p[0].second]; // max value of row_0 = 9.1
}
Jun 4, 2019 at 8:04am
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;

struct element
{
   double value;
   int i, j;
};

//======================================================================

vector<element> largestN( const vector< vector<double> > &M, int N )
{
   vector<element> V;

   // Put all elements of M (with their row/column tags) in a 1-d vector
   for ( int i = 0; i < M.size(); i++ )
   {
      for ( int j = 0; j < M[i].size(); j++ ) V.push_back( { M[i][j], i, j } );
   }

   // Partial sort to get the N highest
   partial_sort( V.begin(), V.begin() + N, V.end(), []( element a, element b ){ return a.value > b.value; } );

   // Discard what we don't want
   V.resize( N );

   return V;
}

//======================================================================

int main()
{
   vector< vector<double> > matrice = { {  1.05, -8.05,  1.0, 8.58, 3.04 },
                                        { 15.05,  8.05, 7.05, 8.58 },
                                        { 11.05, 88.05, 7.06 },
                                        {-12.05, -8.05 }
                                      };

   vector<element> L = largestN( matrice, matrice.size() );
   for ( int n = 0; n < L.size(); n++ )
   {
       cout << "The " << n << " largest is " << L[n].value << " at index (" << L[n].i << ", " << L[n].j << ")\n";
   }
}


The 0 largest is 88.05 at index (2, 1)
The 1 largest is 15.05 at index (1, 0)
The 2 largest is 11.05 at index (2, 0)
The 3 largest is 8.58 at index (0, 3)


If you prefer to count from 1, make the relevant line
cout << "The " << n + 1 << " largest is " << ...

Last edited on Jun 4, 2019 at 8:18am
Topic archived. No new replies allowed.