I want a list of strings sorted first by a number, and if the number is equal to 0, then sort it alphabetically.
Let's say I have :
struct numberedString{string s;
int n;
}
I have an array numberedString a[]
how do I sort the entries in the array using std::sort()
? I think I first need to sort all the numberedString.s
and then sort by the numberedString.n
, but I don't see how exactly to do this ?
Ask and you shall receive. Here you go.
struct functor
{
bool operator() (const numberedString& a,
const numberedString& b)
{
if ((a.n != 0) && (b.n != 0))
{
return a.n < b.n;
}
return a.s < b.s;
}
};
struct numberedString
{
string s;
int n;
bool operator<(const numberedString& other) const
{
if ((n != 0) && (other.n != 0))
{
return n < other.n;
}
return s < other.s;
}
};
Usage:
Overloading the operator<
allows functions to compare instances of your structure naturally:
numberedString c, d;
if (c < d)
{
cout << "c < d\n";
}
else
{
cout << "c >= d\n";
}
The functor allows you to pass a comparison algorithm to ordering functions like std::sort
:
numberedString array[25];
std::sort(&array[0], &array[25], functor);
Note: See std::sort for exact syntax.
BTW, what are the rules for when one variable has a number of zero and the other doesn't?
Basically your structure is so trivial that you could replace it with a std::pair
.
using numberedString = std::pair<int, std::string>;
Then you could just use std::sort
in the ordinary way and due to the std::pair
lexicographical compare, you'll get you're desired effect, simple and without defining a custom comparator (example below):
#include <iostream>
#include <utility>
#include <vector>
#include <string>
#include <algorithm>
using numberedString = std::pair<int, std::string>;
int main() {
numberedString vec1[] = {{4, "four"}, {2, "two"}, {1, "one"}};
std::sort(std::begin(vec1), std::end(vec1));
for(auto &&i : vec1) std::cout << i.first << " -- " << i.second << '\n';
std::cout << std::endl;
numberedString vec2[] = {{0, "four"}, {0, "two"}, {0, "one"}};
std::sort(std::begin(vec2), std::end(vec2));
for(auto &&i : vec2) std::cout << i.first << " -- " << i.second << '\n';
}
LIVE DEMO