Сортировка по типу Символы-Цифры-Латиница-Кирилица

Решил написать сортировку, а точнее натуральную, которая отображала бы всё в таком порядке Символы-Цифры-Латиница-Кирилица (вроде именно ORDER BY работает в sql таким образом). Мне бы приглянулся любой пример на любом языке программирования, но я пишу это всё дело на qt. Пока что вышло вот так

bool lessThan(const QModelIndex &source_left, const QModelIndex &source_right) const override
{
    const QVariant leftData = sourceModel()->data(source_left, IZoneModel::NameRole);
    const QVariant rightData = sourceModel()->data(source_right, IZoneModel::NameRole);

    if (!leftData.canConvert<QString>() || !rightData.canConvert<QString>())
    {
        qDebug() << "DetectionFilter error! Impossible to conver type!";
        return false;
    }

    const auto displayStringList = [](const QStringList& stringList){
        QString result;

        for (const auto& string : stringList) {
            result += string + " ";
        }

        qDebug() << result;
    };

    // Убираем пробелы и точки, если они есть
    //                                            \\ удаляем пробелы \\ разделяем на слова по точкам
    const QStringList leftParse = leftData.value<QString>().replace(" ", "").split(".");
    const QStringList rightParse = rightData.value<QString>().replace(" ", "").split(".");

    // Находим минимальное количество столбцов среди двух сравниваемых имён
    int minCountColumns = leftParse.size();

    if (minCountColumns > rightParse.size())
        minCountColumns = rightParse.size();

    static const QRegExp isDigit("\\d*");

    displayStringList(leftParse);

    for (int i = 0; i < minCountColumns; ++i) {
        const QString lValue = leftParse.at(i);
        const QString rValue = rightParse.at(i);

        if (isDigit.exactMatch(lValue) && isDigit.exactMatch(rValue)) {
            return lValue.toInt() - rValue.toInt();
        } else if (isDigit.exactMatch(lValue) && !isDigit.exactMatch(rValue)) {
            return false;
        } else if (!isDigit.exactMatch(lValue) && isDigit.exactMatch(rValue)) {
            return true;
        } else {
            return lValue.toInt() > rValue.toInt() ? true : false;
        }
    }

Стоит отметить, что в словах могут быть точки (кроме начала и конца выражения), и цифры в любом месте, также как и символы.

Пример:

In: 
zone324.азаза
zone1.азаза
зона2
зона1


Out: 
zone1.азаза
zone324.азаза
зона1
зона2

Ответы (1 шт):

Автор решения: Aziz Umarov

Думаю можно как-то так, не весь алгоритм но ваш пример решает

const arr = ['zone324.азаза','zone1.азаза','зона21','зона3'];

const result = arr.sort((a,b) => {
let aSplit = a.split(/(\d+)/);
let bSplit = b.split(/(\d+)/);
if (aSplit[0] != bSplit[0]) { 
    if (isNaN(+aSplit[0]) || isNaN(+bSplit[0])){      
      return aSplit[0].localeCompare(bSplit[0],'en');
    }
    else {
      return (+aSplit[0])-(+bSplit[0]);
    }
} else { 
    if (isNaN(+aSplit[1]) || isNaN(+bSplit[1])){
      return aSplit[1].localeCompare(bSplit[1],'en');
    }
    else {
     return (+aSplit[1])-(+bSplit[1]);
    }
 }
});

console.log(result);

→ Ссылка