Sorting strings with numerical digits in it

c++, string

Solution

Since the character encoded values of numerals are ordered in the same order as the numbers they represent, you can do string comparison on the last four digits:

#include <cstring>
#include <string>

// Requires: a.size() >= 2, b.size() >= 2
bool two_less(std::string const & a, std::string const & b)
{
    return std::strcmp(a.data() + 2, b.data() + 2) < 0;
}

Now use `sort` with predicate:

#include <algorithm>
#include <vector>

std::vector<std::string> data { "7X1234", "YX1236" };

std::sort(data.begin(), data.end(), two_less);

In C++11, and in particular if you have no repeated use for this, you can also use a lambda directly in the `sort` call:

std::sort(data.begin(), data.end(),
         [](std::string const & a, std::string const & b)
         { return std::strcmp(a.data() + 2, b.data() + 2) < 0; });

Then you can even make the number "2" a captured variable if you need to vary it.

Problem

I have strings like `7X1234 XY1236 NM1235`. I want to sort this strings using last 4 numerical digits only ignoring the initial two alphabets. Also, I want to compare those numerical digits to see if they are sequential. One way to achieve this I can think of is to split these strings between alphabets and numerals as (`7X and 1234`) and work lexical cast the numeral string to int and work on it. But, how can I associate the alphabet part again to the numeral part that is how to prefix `7X` again to `1234` at the end when the numeral strings are sorted and compared in `C++`? In short if I have `7X1234 XY1236 NM1235 BV1238` I need to get `7X1234 NM1235 XY1236 BV1238` I did not elaborate that I wanted to find out if the numerical part of strings are sequential. Right now when I have just ints like 1234 1236 1235 1238 I do something like below ``` std::vector<int> sortedDigits{1234 1235 1236 1238}; int count = 1; int pos = 0; std::vector<std::pair<int, int> > myVec; myVec.push_back(std::make_pair(sortedDigits[pos], count)); for(size_t i = 1; i < sortedDigits.size(); ++i) { if(sortedDigits[i] != (sortedDigits[i-1] + 1)) { count = 1; myVec.push_back(std::make_pair(sortedDigits[i], count) ); ++pos; } else { sortedDigits[pos].second = ++count; } } ``` So at the end I get `(1234, 3)` and `(1238, 1)` I don't know how can I get something like this when strings are there?

Original source