Russian Qt Forum
Ноябрь 24, 2024, 09:37 *
Добро пожаловать, Гость. Пожалуйста, войдите или зарегистрируйтесь.
Вам не пришло письмо с кодом активации?

Войти
 
  Начало   Форум  WIKI (Вики)FAQ Помощь Поиск Войти Регистрация  

Страниц: [1] 2   Вниз
  Печать  
Автор Тема: Сортировка строк и QRegExp  (Прочитано 9331 раз)
Fregloin
Супер
******
Offline Offline

Сообщений: 1025


Просмотр профиля
« : Октябрь 07, 2014, 17:10 »

Привет. Посоветуйте как сделать правильно сортировку. Есть строки вида "1","5","7/9","8c" и т.д. Т.е. сначала всегда идет число, и может быть за ним еще символы. Нужно отсортировать так, как будто кроме числа в строке больше ничего нет. В RegExp я не сильно разбираюсь к сожалению. По документации не понял как это сделать правильно.
Записан
kambala
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 4747



Просмотр профиля WWW
« Ответ #1 : Октябрь 07, 2014, 17:16 »

по-моему проще ручками вырезать ненужные символы, отсортировать полученные строки стандартным способом и после этого соответственно переставить исходные строки.

или еще проще: если есть возможность использовать предикат сортировки, то в нем и вырезать лишние символы и возвращать результат сравнения чисел.
Записан

Изучением C++ вымощена дорога в Qt.

UTF-8 has been around since 1993 and Unicode 2.0 since 1996; if you have created any 8-bit character content since 1996 in anything other than UTF-8, then I hate you. © Matt Gallagher
alex312
Хакер
*****
Offline Offline

Сообщений: 606



Просмотр профиля
« Ответ #2 : Октябрь 07, 2014, 17:21 »

проще взять и отсртировать как есть. проблема в чем?

Вот код:
Код
C++ (Qt)
#include <QCoreApplication>
#include <algorithm>
#include <QStringList>
#include <QDebug>
 
int main(int argc, char *argv[])
{
   QStringList list;
   list <<"8c" << "1"<<"5"<<"7/9" ;
 
   std::sort(list.begin(),list.end());
   qDebug() << list;
 
   return 0;
}
 
вот вывод : ("1", "5", "7/9", "8c")
« Последнее редактирование: Октябрь 07, 2014, 17:29 от alex312 » Записан
m_ax
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 2095



Просмотр профиля
« Ответ #3 : Октябрь 07, 2014, 18:08 »

проще взять и отсртировать как есть. проблема в чем?
Это будет работать только для положительных целых чисел меньших 10..
« Последнее редактирование: Октябрь 07, 2014, 18:12 от m_ax » Записан

Над водой луна двурога. Сяду выпью за Ван Гога. Хорошо, что кот не пьет, Он и так меня поймет..

Arch Linux Plasma 5
Fregloin
Супер
******
Offline Offline

Сообщений: 1025


Просмотр профиля
« Ответ #4 : Октябрь 08, 2014, 17:14 »

проблема в том, что если просто сортировать, то все что с символами будет вначале списка, а не там где надо, т.к. у меня предикат сортировки

Код:
bool sort_func(QString s1, QString s2)
{
return s1.toInt()<s2.toInt();
}
Записан
OKTA
Гость
« Ответ #5 : Октябрь 08, 2014, 17:27 »

Только чуть исправить согласно правилам QRegExp
/^([\d]+).*$/
Проверял тут, если что http://regex101.com/
Записан
GreatSnake
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 2921



Просмотр профиля
« Ответ #6 : Октябрь 08, 2014, 17:37 »

Для такого случая лучше использовать натуральную сортировку.
Можно использовать функцию strnatcmp().
Код
C++ (Qt)
qSort( l.begin(), l.end(), []( const QString& s1, const QString& s2 ) {
   return strnatcmp( s1.toLocal8Bit().constData(), s2.toLocal8Bit().constData() ) < 0;
} );
 

PS. вот здесь уже готовое решение.
« Последнее редактирование: Октябрь 08, 2014, 17:44 от GreatSnake » Записан

Qt 5.11/4.8.7 (X11/Win)
kambala
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 4747



Просмотр профиля WWW
« Ответ #7 : Октябрь 08, 2014, 18:42 »

Только чуть исправить согласно правилам QRegExp
/^([\d]+).*$/
Проверял тут, если что http://regex101.com/
если я правильно понял вопрос, то надо не первые цифры строки обрабатывать, а вообще все, т.е. "a56dsdf/12" => 5612
Записан

Изучением C++ вымощена дорога в Qt.

UTF-8 has been around since 1993 and Unicode 2.0 since 1996; if you have created any 8-bit character content since 1996 in anything other than UTF-8, then I hate you. © Matt Gallagher
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« Ответ #8 : Октябрь 09, 2014, 10:24 »

Сколько усилий приложено чтобы.. избежать написания десятка строк! Что тут военного и зачем искать "готовое решение" - хз

Код
C++ (Qt)
bool IsLess( const QString & s1, const QString & s2 )
{
int limit = qMin(s1.size(), s2.size());
for (int i = 0; i < limit; ++i) {
bool digit1 = s1[i].isDigit();
bool digit2 = s2[i].isDigit();
if (digit1 && digit2) {
if (s1[i] == s2[i]) continue;
return s1[i] < s2[i];
}
return !digit1 && digit2;
}
return false;
}
 

если я правильно понял вопрос, то надо не первые цифры строки обрабатывать, а вообще все, т.е. "a56dsdf/12" => 5612
Ну можно и так, чуть изменим

Код
C++ (Qt)
inline bool NextDigit( const QString & s, int & index )
{
while (index < s.size())
if (s[index++].isDigit()) return true;
 
return false;
}
 
bool IsLess2( const QString & s1, const QString & s2 )
{
int i1 = 0, i2 = 0;
while (true) {
bool digit1 = NextDigit(s1, i1);
bool digit2 = NextDigit(s2, i2);
if (digit1 && digit2) {
QChar c1 = s1[i1 - 1];
QChar c2 = s2[i2 - 1];
if (c1 == c2) continue;
return c1 < c2;
}
return !digit1 && digit2;
}
return false;
}
 
Записан
GreatSnake
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 2921



Просмотр профиля
« Ответ #9 : Октябрь 09, 2014, 10:34 »

Сколько усилий приложено чтобы.. избежать написания десятка строк! Что тут военного и зачем искать "готовое решение" - хз
Если TC устроит строковая, а не натуральная сортировка, то да, согласен.
Только имхо, коли разговор зашел про числа, то и сравнивать нужно числа.

PS. на самом деле мне до сих пор непонятно, почему в Qt нет натуральной сортировки строк, без которой представление данных в таблицах просто кривое.
« Последнее редактирование: Октябрь 09, 2014, 11:02 от GreatSnake » Записан

Qt 5.11/4.8.7 (X11/Win)
m_ax
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 2095



Просмотр профиля
« Ответ #10 : Октябрь 09, 2014, 11:26 »

Сколько усилий приложено чтобы.. избежать написания десятка строк! Что тут военного и зачем искать "готовое решение" - хз

Код
C++ (Qt)
bool IsLess( const QString & s1, const QString & s2 )
{
int limit = qMin(s1.size(), s2.size());
for (int i = 0; i < limit; ++i) {
bool digit1 = s1[i].isDigit();
bool digit2 = s2[i].isDigit();
if (digit1 && digit2) {
if (s1[i] == s2[i]) continue;
return s1[i] < s2[i];
}
return !digit1 && digit2;
}
return false;
}
 

если я правильно понял вопрос, то надо не первые цифры строки обрабатывать, а вообще все, т.е. "a56dsdf/12" => 5612
Ну можно и так, чуть изменим

Код
C++ (Qt)
inline bool NextDigit( const QString & s, int & index )
{
while (index < s.size())
if (s[index++].isDigit()) return true;
 
return false;
}
 
bool IsLess2( const QString & s1, const QString & s2 )
{
int i1 = 0, i2 = 0;
while (true) {
bool digit1 = NextDigit(s1, i1);
bool digit2 = NextDigit(s2, i2);
if (digit1 && digit2) {
QChar c1 = s1[i1 - 1];
QChar c2 = s2[i2 - 1];
if (c1 == c2) continue;
return c1 < c2;
}
return !digit1 && digit2;
}
return false;
}
 
Это не будет работать, например с такой последовательностью:
Код
C++ (Qt)
list <<"8c" << "g93" << "10"<<"5"<<"7/9" ;
 
вывод будет такой:
("10", "5", "7/9", "8c", "g93")


А если есть отрицательные числа?

Вообще, для таких задач идеально подходит лаконичный и прозрачный boost::xpressive, с которым это всё записывается прямо в лямбде в две строчки..

Но мы, конечно же, предпочитаем хардкор  Улыбающийся

 
« Последнее редактирование: Октябрь 09, 2014, 11:32 от m_ax » Записан

Над водой луна двурога. Сяду выпью за Ван Гога. Хорошо, что кот не пьет, Он и так меня поймет..

Arch Linux Plasma 5
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« Ответ #11 : Октябрь 09, 2014, 12:59 »

Если TC устроит строковая, а не натуральная сортировка, то да, согласен.
А если нет, так что? Улыбающийся  Ну давайте "натуральную"
Код
C++ (Qt)
int Beg2Number( const QString & s )
{
char * end;
return strtol(s.toAscii().constData(), &end, 10);
}

Это не будет работать, например с такой последовательностью:
list <<"8c" << "g93" << "10"<<"5"<<"7/9" ;
вывод будет такой:
("10", "5", "7/9", "8c", "g93")
А какой Вы хотели? ТС ясно сказал - первым всегда идет число

А если есть отрицательные числа?
А если числа с точкой? Или в инженерном формате? Определитесь что хотите, тогда и спрашивайте

Вообще, для таких задач идеально подходит лаконичный и прозрачный boost::xpressive, с которым это всё записывается прямо в лямбде в две строчки..

Но мы, конечно же, предпочитаем хардкор  Улыбающийся
А Вы без дуста что-то умеете делать?  Улыбающийся
Записан
m_ax
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 2095



Просмотр профиля
« Ответ #12 : Октябрь 09, 2014, 18:56 »

Цитировать
А какой Вы хотели? ТС ясно сказал - первым всегда идет число
Да у Вас даже так работать не будет..
list <<"8" << "23" << "101"<<"5"<<"7" ;
вывод:
("101", "23", "5", "7", "8")
Это нормально?

Цитировать
А Вы без дуста что-то умеете делать?
Буст - это инструмент для решения задач (причём очень мощный).. чтоб не тратить время на свои поделки (которые, как мы видим, ещё и не работают как нужно)   

   
Записан

Над водой луна двурога. Сяду выпью за Ван Гога. Хорошо, что кот не пьет, Он и так меня поймет..

Arch Linux Plasma 5
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« Ответ #13 : Октябрь 10, 2014, 10:23 »

Да у Вас даже так работать не будет..
list <<"8" << "23" << "101"<<"5"<<"7" ;
вывод:
("101", "23", "5", "7", "8")
Это нормально?
Как ни странно - да Улыбающийся Именно так Qt сортирует такие строки, это легко проверить
Код
C++ (Qt)
QStringList lst;
lst << "8" << "23" << "101" << "5" << "7";
qSort(lst.begin(), lst.end());
for (int i = 0; i < lst.size(); ++i)
qDebug() << lst[i];
 
Выше уже говорилось что такое часто выглядит глуповасто, но ТС сказал
Нужно отсортировать так, как будто кроме числа в строке больше ничего нет.
Значит имеется ввиду сортировка строк Qt.

Да, и предъявляем реализацию
Вообще, для таких задач идеально подходит лаконичный и прозрачный boost::xpressive, с которым это всё записывается прямо в лямбде в две строчки..
Посмотрим что же там такого хорошего..

Буст - это инструмент для решения задач (причём очень мощный).. чтоб не тратить время на свои поделки (которые, как мы видим, ещё и не работают как нужно)
Все хорошо в меру - а Вы ее давно потеряли. Упорно избегая "задачек для начинающих" Вы оказываетесь беспомощны как только надо вылезти из скорлупы std/boost
Записан
m_ax
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 2095



Просмотр профиля
« Ответ #14 : Октябрь 10, 2014, 12:15 »

Цитировать
Значит имеется ввиду сортировка строк Qt.
А мне так не кажется.. Из того, что сказал ТС этого не следует.

Цитировать
Да, и предъявляем реализацию
Пожалуйста:
Код
C++ (Qt)
lst.sort([](const std::string& str1, const std::string& str2)->bool
       {
           sregex regex = (s1 = +_d) >> *~_d;
           smatch what1, what2;
           if (regex_search(str1, what1, regex) && regex_search(str2, what2, regex))
               return std::stoi(what1[1]) < std::stoi(what2[1]);
 
           return false;
 
       });
 

Цитировать
Вы оказываетесь беспомощны как только надо вылезти из скорлупы std/boost
Опять глупости..
« Последнее редактирование: Октябрь 10, 2014, 12:22 от m_ax » Записан

Над водой луна двурога. Сяду выпью за Ван Гога. Хорошо, что кот не пьет, Он и так меня поймет..

Arch Linux Plasma 5
Страниц: [1] 2   Вверх
  Печать  
 
Перейти в:  


Страница сгенерирована за 0.285 секунд. Запросов: 23.