Russian Qt Forum

Qt => Общие вопросы => Тема начата: Fregloin от Октябрь 07, 2014, 17:10



Название: Сортировка строк и QRegExp
Отправлено: Fregloin от Октябрь 07, 2014, 17:10
Привет. Посоветуйте как сделать правильно сортировку. Есть строки вида "1","5","7/9","8c" и т.д. Т.е. сначала всегда идет число, и может быть за ним еще символы. Нужно отсортировать так, как будто кроме числа в строке больше ничего нет. В RegExp я не сильно разбираюсь к сожалению. По документации не понял как это сделать правильно.


Название: Re: Сортировка строк и QRegExp
Отправлено: kambala от Октябрь 07, 2014, 17:16
по-моему проще ручками вырезать ненужные символы, отсортировать полученные строки стандартным способом и после этого соответственно переставить исходные строки.

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


Название: Re: Сортировка строк и QRegExp
Отправлено: alex312 от Октябрь 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")


Название: Re: Сортировка строк и QRegExp
Отправлено: m_ax от Октябрь 07, 2014, 18:08
проще взять и отсртировать как есть. проблема в чем?
Это будет работать только для положительных целых чисел меньших 10..


Название: Re: Сортировка строк и QRegExp
Отправлено: Fregloin от Октябрь 08, 2014, 17:14
проблема в том, что если просто сортировать, то все что с символами будет вначале списка, а не там где надо, т.к. у меня предикат сортировки

Код:
bool sort_func(QString s1, QString s2)
{
return s1.toInt()<s2.toInt();
}


Название: Re: Сортировка строк и QRegExp
Отправлено: OKTA от Октябрь 08, 2014, 17:27
Только чуть исправить согласно правилам QRegExp
/^([\d]+).*$/
Проверял тут, если что http://regex101.com/


Название: Re: Сортировка строк и QRegExp
Отправлено: GreatSnake от Октябрь 08, 2014, 17:37
Для такого случая лучше использовать натуральную сортировку.
Можно использовать функцию strnatcmp() (http://sourcefrog.net/projects/natsort/strnatcmp.c).
Код
C++ (Qt)
qSort( l.begin(), l.end(), []( const QString& s1, const QString& s2 ) {
   return strnatcmp( s1.toLocal8Bit().constData(), s2.toLocal8Bit().constData() ) < 0;
} );
 

PS. вот здесь (http://www.forum.crossplatform.ru/index.php?showtopic=6244) уже готовое решение.


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


Название: Re: Сортировка строк и QRegExp
Отправлено: Igors от Октябрь 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;
}
 


Название: Re: Сортировка строк и QRegExp
Отправлено: GreatSnake от Октябрь 09, 2014, 10:34
Сколько усилий приложено чтобы.. избежать написания десятка строк! Что тут военного и зачем искать "готовое решение" - хз
Если TC устроит строковая, а не натуральная сортировка, то да, согласен.
Только имхо, коли разговор зашел про числа, то и сравнивать нужно числа.

PS. на самом деле мне до сих пор непонятно, почему в Qt нет натуральной сортировки строк, без которой представление данных в таблицах просто кривое.


Название: Re: Сортировка строк и QRegExp
Отправлено: m_ax от Октябрь 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, с которым это всё записывается прямо в лямбде в две строчки..

Но мы, конечно же, предпочитаем хардкор  :)

 


Название: Re: Сортировка строк и QRegExp
Отправлено: Igors от Октябрь 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, с которым это всё записывается прямо в лямбде в две строчки..

Но мы, конечно же, предпочитаем хардкор  :)
А Вы без дуста что-то умеете делать?  :)


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

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

   


Название: Re: Сортировка строк и QRegExp
Отправлено: Igors от Октябрь 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


Название: Re: Сортировка строк и QRegExp
Отправлено: m_ax от Октябрь 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
Опять глупости..


Название: Re: Сортировка строк и QRegExp
Отправлено: Igors от Октябрь 10, 2014, 13:32
Ну хорошо, пусть надо сортировать "по числу".
Пожалуйста:
Код
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;
 
       });
 
И к чему весь этот огород с regexp? Ведь stoi сводится к strtol который уже делает все что нужно: конвертирует строку в число до того символа когда конверсия невозможна. Можно было просто записать
Код
C++ (Qt)
lst.sort([](const std::string& str1, const std::string& str2)->bool
       {
          return std::stoi(str1) < std::stoi(str2);
       );
 
Но, видимо, Вам хотелось пустить пыль в глаза "чем-то особенным" (кто такие s1 _d - хз). Ваш код постоянно показывает "широту Ваших познаний" - но далековато от решаемой задачи  :)



Название: Re: Сортировка строк и QRegExp
Отправлено: m_ax от Октябрь 10, 2014, 13:49
Цитировать
Ведь stoi сводится к strtol который уже делает все что нужно: конвертирует строку в число до того символа когда конверсия невозможна. Можно было просто записать
Да, согласен, здесь можно было бы и без xpressive обойтись..
Код
C++ (Qt)
lst.sort([](const std::string& str1, const std::string& str2)->bool
   {
       try {
           return std::stoi(str1) < std::stoi(str2);
       } catch (...) {
           return false;
       }
   });