Problem with sorting with the iterator.

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;

}
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
Hey! Thanks for the reply, could you please exemplify?
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?
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.
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
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
}
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
Topic archived. No new replies allowed.