Sort 2D vector by Multiple columns

I'm using the following boost algorithm to sort my 2D vector.

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
#include <vector>
#include <boost/algorithm/string.hpp>

using namespace std;


class StringListCompare
{
public:
  explicit StringListCompare(int column) : m_column(column) {}
  bool operator()(const vector<string>& lhs, const vector<string>& rhs)
  {
    // what do we do if lhs or rhs don't have (m_column + 1) elements?
    return lhs[m_column] < rhs[m_column];
  }
private:
  int m_column;
};

int main()
{
  std::vector <std::vector <std::string> > data;
  std::vector <std::string> temp;
  //
  // Load 2D vector 
  sort(data.begin(), data.end(), StringListCompare(2));

  //Print 2D vector after sorting by 2nd column
}

Here I can sort the vector by Only one column which i specified as argument. But I want to sort this vector by two columns. My first column should be in sorted. According the first column sort I want to sort the vector again by 2nd column. How can i do this ?

I want to sort first by the first column, and then sort the ones with equal first column to be sorted by the second column?
Last edited on
For example you can change you comparsion function.
In following code it will sort by second column and equal elements will be sorted by third column:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
class StringListCompare
{
public:
  explicit StringListCompare(int column) : m_column(column) {}
  bool operator()(const vector<string>& lhs, const vector<string>& rhs)
  {
      if lhs[m_column] = rhs[m_column];
        return lhs[m_column + 1] < rhs[m_column + 1];
      else
        return lhs[m_column] < rhs[m_column];
  }
private:
  int m_column;
};
Thank you so much Mr. MiiNiPaa. But its sorting by two adjacent columns. But I want to sort by first column and equal elements will be sorted by third column or any number of column. The Secondary column should be passed as parameter. I need to take decision to sort the table by which columns. And I didn't check the above code for Date type fields. Will it be work for Date type fields ? Sorry. I need to check it . And if it is not, Please How can I change the above function to do the two operations which i mentioned.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
class StringListCompare
{

public:
  explicit StringListCompare(int column, int column2) : m_column(column), m_column2(column2) {}
  bool operator()(const vector<string>& lhs, const vector<string>& rhs)
  {
      if (lhs[m_column] == rhs[m_column])
        return lhs[m_column2] < rhs[m_column2];
      else
        return lhs[m_column] < rhs[m_column];
  }
private:
  int m_column;
  int m_column2;
};
Thank you so much Mr. MiiNiPaa.
I struck once again :( . If i need to sort the first column by integer type means, how can i do this ? I checked the above code . But its not working correctly for 1,2,3,11,4,5. I came with the sorting result of 1,11,2,3,4,5 . I know why the result came like this. Its depends on ascii Values. But My program should be smart . How can i change this code for checking other data type also. I tried this. But not working.

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
class StringListCompare
{

public:
  explicit StringListCompare(int column, int column2, string fCol, string sCol) : m_column(column), m_column2(column2) , fColType(fCol), sColType(sCol) {}
 
  bool operator()(const vector<string>& lhs, const vector<string>& rhs)
  {
	 
		if (lhs[m_column] == rhs[m_column])
		{
			 if (fColType.compare("string")==0)
				return lhs[m_column2] < rhs[m_column2];
			else  if (fColType.compare("number")==0)
				return atoi(lhs[m_column2]) < atoi(rhs[m_column2]);
		}
			
		else
		{
			 if (fColType.compare("string")==0)
				return lhs[m_column] < rhs[m_column];
			else  if (fColType.compare("number")==0)
				return atoi(lhs[m_column]) < atoi(rhs[m_column]);
		}
	
  }
private:
  int m_column;
  int m_column2;
  string fColType;
  string sColType;
};



I got the below error.

error: cannot convert ‘const std::basic_string<char>’ to ‘const char*’ for argument ‘1’ to ‘int atoi(const char*)’


I aware of this error. But I need solution for this problem . I want to sort this 2D vector string array for other data Types also . How can i do this ?
Use stoi() instead of atoi()
I tried like this. I got below errors. I tried to find out which header file for stoi() function in ubuntu. I couldn't get it.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
 bool operator()(const vector<string>& lhs, const vector<string>& rhs)
  {
	 
		if (lhs[m_column] == rhs[m_column])
		{
			 if (fColType.compare("string")==0)
				return lhs[m_column2] < rhs[m_column2];
			else  if (fColType.compare("number")==0)
				return stoi(lhs[m_column2]) < stoi(rhs[m_column2]);
		}
			
		else
		{
			 if (fColType.compare("string")==0)
				return lhs[m_column] < rhs[m_column];
			else  if (fColType.compare("number")==0)
				return stoi(lhs[m_column]) < stoi(rhs[m_column]);
		}
	
  }


My errors

error: In member function ‘bool StringListCompare::operator()(const std::vector<std::basic_string<char> >&, const std::vector<std::basic_string<char> >&)’:
error: ‘stoi’ was not declared in this scope
error: ‘stoi’ was not declared in this scope
warning: control reaches end of non-void function [-Wreturn-type]
Compilation failed.

#include <boost/algorithm/string.hpp>
Why not: #include <string> ? std::stoi() function declared in <string> header.
Of cource you can use some_string_variable.c_str() if boost string support it.
I have used both headers . But still I'm getting the same error. Is there any other option to fix my problem ?? or Any other algorithm available for this type of sorting ?
You can use some_string.c_str() to convert it to c-string and use atoi() on them.
sorry. I couldn't get you correctly. Can you please change my code and post it here ?
1
2
else  if (fColType.compare("number")==0)
return atoi(lhs[m_column2]) < atoi(rhs[m_column2]);

↓↓↓
1
2
else  if (fColType.compare("number")==0)
return atoi(lhs[m_column2].c_str) < atoi(rhs[m_column2].c_str);

http://cplusplus.com/reference/string/basic_string/c_str/
I changed this code as you said. But I got the below error .

Error:
g++ -Wall -c "twocolsort.cpp" (in directory: /home/heartly/Cppprograms)
twocolsort.cpp: In member function ‘bool StringListCompare::operator()(const std::vector<std::basic_string<char> >&, const std::vector<std::basic_string<char> >&)’:
error: argument of type ‘const char* (std::basic_string<char>::)()const’ does not match ‘const char*’


Changed Code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
bool operator()(const vector<string>& lhs, const vector<string>& rhs)
  {
	 
		if (lhs[m_column] == rhs[m_column])
		{
			 if (fColType.compare("string")==0)
				return lhs[m_column2] < rhs[m_column2];
			else  if (fColType.compare("number")==0)
				return atoi(lhs[m_column2].c_str) < atoi(rhs[m_column2].c_str);
		}
			
		else
		{
			 if (fColType.compare("string")==0)
				return lhs[m_column] < rhs[m_column];
			else  if (fColType.compare("number")==0)
				return atoi(lhs[m_column].c_str) < atoi(rhs[m_column].c_str);
		}
	
  }


How can I fix this bug ?
it's c_str(), not c_str
oops :) Now I'm corrected my mistake. Thank you so much Mr. MiiNiPaa . And Now I'm going to make a functiont for Date type also..
There was a bug again.
I tried this.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
bool operator()(const vector<string>& lhs, const vector<string>& rhs)
  {
	 
		if (lhs[m_column] == rhs[m_column])
		{
			 if (sColType.compare("string")==0)
				return lhs[m_column2] < rhs[m_column2];
			else  if (sColType.compare("number")==0)
				return atoi(lhs[m_column2].c_str()) < atoi(rhs[m_column2].c_str());
		}
			
		else
		{
			 if (fColType.compare("string")==0)
				return lhs[m_column] < rhs[m_column];
			else  if (fColType.compare("number")==0)
				return atoi(lhs[m_column].c_str()) < atoi(rhs[m_column].c_str());
		}
	
  }


This is my original Vector Data.
[1] [hello3] [01/01/2000] 
  [2] [hello2] [01/02/2010] 
  [3] [hello3] [05/01/2000] 
  [1] [hello2] [08/09/2000] 
  [2] [hello3] [02/05/2000] 
  [3] [hello2] [09/01/2000] 
  [1.5] [hello1] [11/08/2000] 
  [2] [hello1] [18/01/2002] 
  [3] [hello1] [20/01/2003]


After running this code

1
2
3
 StringListCompare compare_column_0(0,1, "number","string");
 sort(data_var.begin(), data_var.end(), compare_column_0);
  cout << "Sorted on column 2:\n" << data_var << endl;


I got the below output. My Second column not sorted properly.
[1] [hello3] [01/01/2000] 
  [1] [hello2] [08/09/2000] 
  [1.5] [hello1] [11/08/2000] 
  [2] [hello2] [01/02/2010] 
  [2] [hello3] [02/05/2000] 
  [2] [hello1] [18/01/2002] 
  [3] [hello3] [05/01/2000] 
  [3] [hello2] [09/01/2000] 
  [3] [hello1] [20/01/2003] 


First column sorted correctly but not second. What is the problem here ?
Last edited on
Working fine. I made a mistake. But I want to post what I have did for Date Type also. Please check it whether it has any bugs or not. I checked for all possible ( I think) values. But Can you please check it whether it will be work on any values ?
This is my code.

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
int PPCheckTwoDate(string sdt,string edt)
{

	char sdtc[11],edtc[11];
	strcpy(sdtc,sdt.c_str());
	strcpy(edtc,edt.c_str());
	int sdd,smm,syy,edd,emm,eyy;

	sscanf(sdtc,"%d/%d/%d",&sdd,&smm,&syy);
	sscanf(edtc,"%d/%d/%d",&edd,&emm,&eyy);
	
        if(eyy > syy)                   // CHECK YEARS 
                return -1;
        else if (eyy == syy)
        {
                if(emm > smm)  return -1;
                else if (emm == smm)
                        if(edd > sdd) return -1;
                        else if(edd == sdd)  return 0;
                        else return 1;
                else  return 1;
        }
        else return 1;

}

class StringListCompare
{

public:
  explicit StringListCompare(int column, int column2, string fCol, string sCol) : m_column(column), m_column2(column2) , fColType(fCol), sColType(sCol) {}
 
 bool operator()(const vector<string>& lhs, const vector<string>& rhs)
  {
	 
		if (lhs[m_column] == rhs[m_column])
		{
			
			 if (sColType.compare("string")==0)
				return lhs[m_column2] < rhs[m_column2];
			else  if (sColType.compare("number")==0)
				return atoi(lhs[m_column2].c_str()) < atoi(rhs[m_column2].c_str());
			else if (sColType.compare("date")==0)
				return PPCheckTwoDate(lhs[m_column2], rhs[m_column2])<0;
		}
			
		else
		{
			 if (fColType.compare("string")==0)
				return lhs[m_column] < rhs[m_column];
			else  if (fColType.compare("number")==0)
				return atoi(lhs[m_column].c_str()) < atoi(rhs[m_column].c_str());
				
			else if (fColType.compare("date")==0)
				return PPCheckTwoDate(lhs[m_column], rhs[m_column])<0;
		}
  }
  

private:
  int m_column;
  int m_column2;
  string fColType;
  string sColType;
};


My Output.
Original:
  [1] [hello3] [01/01/2000] 
  [2] [hello2] [01/02/2010] 
  [3] [hello3] [05/01/2000] 
  [1] [hello2] [08/09/2000] 
  [2] [hello3] [02/05/1999] 
  [3] [hello2] [09/01/2000] 
  [11] [hello1] [11/08/2000] 
  [2] [hello1] [18/01/1990] 
  [3] [hello1] [20/01/2003] 
  [1.5] [hello4] [08/09/2000] 
  [12] [hello6] [02/05/2000] 
  [1.5] [hello7] [09/01/2000] 
  [1.5] [hello8] [11/08/2000] 
  [12] [hello9] [18/01/2002] 
  [23] [hello10] [20/01/2003] 

Sorted on column 0 and 2: ( Number and String )
  [1] [hello2] [08/09/2000] 
  [1] [hello3] [01/01/2000] 
  [1.5] [hello4] [08/09/2000] 
  [1.5] [hello7] [09/01/2000] 
  [1.5] [hello8] [11/08/2000] 
  [2] [hello1] [18/01/1990] 
  [2] [hello2] [01/02/2010] 
  [2] [hello3] [02/05/1999] 
  [3] [hello1] [20/01/2003] 
  [3] [hello2] [09/01/2000] 
  [3] [hello3] [05/01/2000] 
  [11] [hello1] [11/08/2000] 
  [12] [hello6] [02/05/2000] 
  [12] [hello9] [18/01/2002] 
  [23] [hello10] [20/01/2003] 

Sorted on column 0 and 2: ( number and Date)
  [1] [hello3] [01/01/2000] 
  [1] [hello2] [08/09/2000] 
  [1.5] [hello7] [09/01/2000] 
  [1.5] [hello8] [11/08/2000] 
  [1.5] [hello4] [08/09/2000] 
  [2] [hello1] [18/01/1990] 
  [2] [hello3] [02/05/1999] 
  [2] [hello2] [01/02/2010] 
  [3] [hello3] [05/01/2000] 
  [3] [hello2] [09/01/2000] 
  [3] [hello1] [20/01/2003] 
  [11] [hello1] [11/08/2000] 
  [12] [hello6] [02/05/2000] 
  [12] [hello9] [18/01/2002] 
  [23] [hello10] [20/01/2003] 


Topic archived. No new replies allowed.