Сортировка по типу Символы-Цифры-Латиница-Кирилица
Решил написать сортировку, а точнее натуральную, которая отображала бы всё в таком порядке Символы-Цифры-Латиница-Кирилица (вроде именно 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);