Edit: Added the lookup table and corrected the tests in getless
.
Here is another solution using std::sort and a function that tests each string and returns true
if one string is less than the other in QWERTY order:
#include <algorithm>
#include <string>
#include <vector>
#include <cctype>
#include <iostream>
typedef std::vector<std::string> StringVect;
std::string sequence = "QWERTYUIOPASDFGHJKLZXCVBNM";
std::vector<int> lookup(26);
bool getless(const std::string& s1, const std::string& s2)
{
for (size_t i = 0; i < std::min(s1.size(), s2.size()); ++i)
if (s1[i] != s2[i])
return (lookup[toupper(s1[i])-'A'] < lookup[toupper(s2[i])-'A']);
return s1.size() < s2.size();
};
int main()
{
StringVect sv = {{ "apple" },{ "pear" },{ "peach" }};
// build the lookup table
int i = 0;
std::for_each(sequence.begin(), sequence.end(), [&](char ch) {lookup[ch-'A'] = i; ++i; });
// sort the data
std::sort(sv.begin(), sv.end(), getless);
// output results
for (auto& s : sv)
std::cout << s << "\n";
}
Live Example
A lookup table is built that maps the character's relative ASCII position to where the character is found in the sequence
string. So for example, lookup[0]
is the position of A
(which is 10), lookup[1]
is the position of B
(which is 23), etc.
The getless
function scans the string and tests the character associated with the i'th
character of each string with the corresponding lookup position.
The for
loop basically "waits for" a character difference in the two strings being compared. If the character in the string for s1
has a lookup value less than the lookup value for the character in s2
, then we immediately return "true", meaning that s1 < s2. Otherwise we return false
if s1 > s2.
If the characters are equal, we keep looping until we run out of characters to compare. If both strings are equal up to the point we exit the for
loop, we return true or false, depending on the length of the strings (a shorter string would mean s1 < s2).