Russian Qt Forum

Qt => Вопросы новичков => Тема начата: Spark от Июль 24, 2013, 21:24



Название: Регулярное выражение с QString
Отправлено: Spark от Июль 24, 2013, 21:24
Это срабатывает:
Код
C++ (Qt)
QString trimmedStr;
...
QRegExp rx(trimmedStr);

Это не рабоатет:
Код
C++ (Qt)
QString trimmedStr;
...
QRegExp rx("\\b(" + trimmedStr + ")\\b");

Возможно ли это?


Название: Re: Регулярное выражение с QString
Отправлено: Alex Custov от Июль 24, 2013, 21:28
что находится в строке и что показывает QRegExp::indexIn() мы должны угадать?


Название: Re: Регулярное выражение с QString
Отправлено: Spark от Июль 24, 2013, 21:41
Простейший частотный анализ текста:

Код
C++ (Qt)
void MainWindow::bufferButtonSave()
{
   QClipboard *clipboard = QApplication::clipboard();
   QString originalText = clipboard->text();
 
   originalText.replace(QRegExp("\\W"), " ");
   originalText.replace(QRegExp("\\d"), " ");
 
       QTextStream fileStream( & originalText );
       QString itemStr, trimmedStr;
       QList< QString > itemList;
 
       QString nnn;
 
 
       text.clear();
 
       do
       {
           // Пословно
           fileStream >>(itemStr);
           // Построчно
//            itemStr = fileStream.readLine();
 
           trimmedStr = itemStr.trimmed();
 
           QRegExp rx(trimmedStr);
 
           int coun(0);
           int pos = 0;
           while ((pos = rx.indexIn(originalText, pos)) != -1)
           {
               ++coun;
               pos += rx.matchedLength();
           }
 
           nnn.setNum(coun);
           trimmedStr = trimmedStr + nnn;
           itemList.prepend( trimmedStr );
 
       } while( !fileStream.atEnd() );
 
       history.enableAdd( true );
 
       for( QList< QString >::const_iterator i = itemList.constBegin(); i != itemList.constEnd(); ++i )
           text.addItem( Text::Item( 1, *i ) );
 
       text.enableAdd( cfg.preferences.storeText );
}

Честно говоря и первый вариант не работает. Но вроде срабатывал. Может показалось. А может уже где накуралесил и не могу определить ошибку.


Название: Re: Регулярное выражение с QString
Отправлено: kambala от Июль 24, 2013, 21:52
где пример входных и выходных данных? сам хоть пробовал ставить qDebug чтобы смотреть что там происходит?

частотный анализ чего — слов?


Название: Re: Регулярное выражение с QString
Отправлено: Spark от Июль 24, 2013, 22:09
где пример входных и выходных данных? сам хоть пробовал ставить qDebug чтобы смотреть что там происходит?

частотный анализ чего — слов?
Да слов.
qDebug не пробовал и не знаю как.
В общем то нашел ошибку. Под утро уже устал. Работает:
Код
C++ (Qt)
void MainWindow::bufferButtonSave()
{
   QClipboard *clipboard = QApplication::clipboard();
   QString originalText = clipboard->text();
 
   originalText.replace(QRegExp("\\W"), " ");
   originalText.replace(QRegExp("\\d"), " ");
 
       QTextStream fileStream( & originalText );
       QString itemStr, trimmedStr;
       QList< QString > itemList;
 
       QString nnn;
 
 
       text.clear();
 
       do
       {
           // Пословно
           fileStream >>(itemStr);
           // Построчно
//            itemStr = fileStream.readLine();
 
           trimmedStr = itemStr.trimmed();
 
           QRegExp rx(trimmedStr);
 
           int coun(0);
           int pos = 0;
           while ((pos = rx.indexIn(originalText, pos)) != -1)
           {
               ++coun;
               ++pos;
           }
 
           nnn.setNum(coun);
           trimmedStr = trimmedStr + nnn;
           itemList.prepend( trimmedStr );
 
       } while( !fileStream.atEnd() );
 
       text.enableAdd( true );
 
       for( QList< QString >::const_iterator i = itemList.constBegin(); i != itemList.constEnd(); ++i )
           text.addItem( Text::Item( 1, *i ) );
 
       text.enableAdd( cfg.preferences.storeText );
}

На входе:
Цитировать
где пример входных и выходных данных? сам хоть пробовал ставить qDebug чтобы смотреть что там происходит?

частотный анализ чего — слов?
На выходе:
Цитировать
где1
пример1
входных1
и1
выходных1
данных1
сам1
хоть1
пробовал1
ставить1
qDebug1
чтобы1
смотреть1
что1
там1
происходит1
частотный1
анализ1
чего1
слов1
40
Пока только не ясно, что за цифра в конце выскакивает. Что то лишнее считает.


Название: Re: Регулярное выражение с QString
Отправлено: kambala от Июль 24, 2013, 22:37
Цитировать
qDebug не пробовал и не знаю как.
открою секрет: http://qt-project.org/doc/qt-4.8/qtglobal.html#qDebug

зачем пробегать по строкам списка через итератор если есть foreach, который укорачивает написание в 2-3 раза?

и кстати вместо QList< QString > можно писать просто QStringList.


Название: Re: Регулярное выражение с QString
Отправлено: Spark от Июль 24, 2013, 22:44
Цитировать
qDebug не пробовал и не знаю как.
открою секрет: http://qt-project.org/doc/qt-4.8/qtglobal.html#qDebug

зачем пробегать по строкам списка через итератор если есть foreach, который укорачивает написание в 2-3 раза?

и кстати вместо QList< QString > можно писать просто QStringList.
Спасибо за помощь. Переделаю.
А не подскажете, что за цифра в конце выскакивает?
Если вывожу список без частотного анализа и сравниваю с похожей программой, то количество слов (пунктов) для подсчета совпадает. Ввел частотный анализ, на один пункт (цифра в конце) больше.


Название: Re: Регулярное выражение с QString
Отправлено: kambala от Июль 24, 2013, 23:05
нет, не подскажу. наверное это цифра 4 с дописанным к ней 0, а не просто число 40. бери qDebug и вперед ;)


Название: Re: Регулярное выражение с QString
Отправлено: Igors от Июль 25, 2013, 09:57
Простейший частотный анализ текста:
Что-то он у Вас не выглядит простым  :) Что нужно? Посчитать частоту слов разделенных пробелами? Это легко сделать напр так
Код
C++ (Qt)
QString src = "This is a text"
QMap <QString, int> theMap;
QStringList lst = src.split(" ");
for (int i = 0; i < lst.size(); ++i)
++theMap[lst[i]];
 
Из Вашего кода трудно понять чего Вы хотите добиться.

Также плохо совать это в MainWindow, как говорят "смешивать бизнес-логику с UI". Каждый начинает с соображений типа "тааа... ото заводить файл, да еще и хедер - напишу прямо здесь - и все дела". Но рано или поздно все приходят к "разложить все по полочкам". Плэтому лучше рано  :)


Название: Re: Регулярное выражение с QString
Отправлено: Old от Июль 25, 2013, 10:16
Это легко сделать напр так
Легко, но не оптимально: первый проход по строке для разбиения по словам, второй проход по уже разбитым словам. Лучше все делать в один проход.




Название: Re: Регулярное выражение с QString
Отправлено: Igors от Июль 25, 2013, 10:28
Легко, но не оптимально: первый проход по строке для разбиения по словам, второй проход по уже разбитым словам. Лучше все делать в один проход.
То да, правду сказать, split - метод лошарный. По-хорошему надо строить что-то типа NextToken, здесь лучше NextWord. Но Вы меня уже затравили обвинениями в велосипедизме - поэтому так  :)


Название: Re: Регулярное выражение с QString
Отправлено: Spark от Июль 25, 2013, 10:37
Простейший частотный анализ текста:
Что-то он у Вас не выглядит простым  :) Что нужно? Посчитать частоту слов разделенных пробелами? Это легко сделать напр так
Код
C++ (Qt)
QString src = "This is a text"
QMap <QString, int> theMap;
QStringList lst = src.split(" ");
for (int i = 0; i < lst.size(); ++i)
++theMap[lst[i]];
 
Из Вашего кода трудно понять чего Вы хотите добиться.

Также плохо совать это в MainWindow, как говорят "смешивать бизнес-логику с UI". Каждый начинает с соображений типа "тааа... ото заводить файл, да еще и хедер - напишу прямо здесь - и все дела". Но рано или поздно все приходят к "разложить все по полочкам". Плэтому лучше рано  :)

Спасибо за советы. Что смогу то постараюсь учесть.
Я не имел ввиду простоту кода.
Если же все таки по нему. То за расчет частоты там не так много отвечает.
Эта фукция отвечает за (думаю и так все ясно):
- Взять любой текст из буфера обмена.
Пословная ветка:
- Заменить все не алфавитные символы на пробелы.
- В цикле сформировать список и заодно посчитать частоту повтора слов. Пробелы слева справа убрать.
- Далее из списка формируется реальная панель со списком слов и частотой употребления. Отправка каждого слова идет уже в другую функцию.
Построчная ветка: Эта часть просто берет каждую строку и формирует список для пользователя без частотного анализа.
Вот так это выглядит:
(http://s019.radikal.ru/i602/1307/30/1d5192ba1159t.jpg) (http://radikal.ru/fp/c73bb19343d24b5499b84462bc9a39df)
Если ваш код снабдить всем необходимым, будет ли он проще? Попробую разобраться и оценить :).

Пока все работает, за исключением не понятной циферки.
На счет qDebug. На сколько понял. Это просто ставить вывод где хочу и куда хочу для отслеживания стуации и компилировать в Дебаг режиме. Компиляция не получается. Запуск программы вылетает с неожиданной ошибкой.


Название: Re: Регулярное выражение с QString
Отправлено: Old от Июль 25, 2013, 10:40
Но Вы меня уже затравили обвинениями в велосипедизме - поэтому так  :)
Причем здесь велосипедизм, все легко делается в цикле типа:
Код
C++ (Qt)
while ((pos = rx.indexIn(originalText, pos)) != -1)
{
   ...
}
 
Как и было у автора темы.


Название: Re: Регулярное выражение с QString
Отправлено: Spark от Июль 25, 2013, 10:47
Может все таки кто нибудь опытным взглядом оценит почему внизу списка дополнительный пункт - просто цифра. Что у меня еще считается? Конечно разберусь, но может кто сможет сразу сказать, что не так?
Предчувствие, что заодно считает начало и конц каждого слова :). Что то напутал с регеспом.


Название: Re: Регулярное выражение с QString
Отправлено: Igors от Июль 25, 2013, 11:48
Отлаживайтесь, напр так
Код
C++ (Qt)
nnn.setNum(coun);
if (coun == 40)
qDebug()  << "opa!  " << trimmedStr;
 
Возможно trimmedStr пустая

Вообще зачем так делать - искать по каждой число ее вхождений?  Это имело бы смысл если словарь задан извне, а если все на руках - да просчитали частоту и сложили в мапу. Нужно вывести по порядку - просто QStringList - (можно тот же самый что вернул split) и из мапы достаете частоту, напр
Код
C++ (Qt)
for (int i = 0; i < lst.size(); ++i)
qDebug()  << lst[i] << "  " << theMap[lst[i]];
 


Название: Re: Регулярное выражение с QString
Отправлено: Spark от Июль 25, 2013, 12:57
Спасибо более менее разобрался. Отладчик выдает:
Цитировать
Отладка запущена
Object::connect: No such slot MainWindow::contextDictsPane( const QPoint & )
Object::connect:  (sender name:   'dictsPane')
Object::connect:  (receiver name: 'MainWindow')
Reloading all the tabs...
Reloading all the tabs...
opa!   ""
Как учесть?


Название: Re: Регулярное выражение с QString
Отправлено: Spark от Июль 25, 2013, 13:50
зачем пробегать по строкам списка через итератор если есть foreach, который укорачивает написание в 2-3 раза?

и кстати вместо QList< QString > можно писать просто QStringList.
Заменил:
Код
C++ (Qt)
       for( QList< QString >::const_iterator i = itemList.constBegin(); i != itemList.constEnd(); ++i )
           text.addItem( Text::Item( 1, *i ) );
На:
Код
C++ (Qt)
          foreach (QString itm, itemList)text.addItem( Text::Item( 1, itm ) );
На этот раз поддается критике :)?
На самом деле важна скорость, полагаю. Поскольку тексты предполагается обрабатывать и внушительных объемов в том числе. А так же сам частотный расчет пока простой. Предполагается постепенно усложнять обработку.


Название: Re: Регулярное выражение с QString
Отправлено: Spark от Июль 25, 2013, 14:26
Если в тексте последним идет пробел или перенос строки, то алгоритм его считает (все пробелы и переносы в тексте). При этом, если в тексте только внутренние пробелы (допустим скопировать часть строки) не считает.


Название: Re: Регулярное выражение с QString
Отправлено: kambala от Июль 25, 2013, 14:42
делай trimmed для исходной строки


Название: Re: Регулярное выражение с QString
Отправлено: Spark от Июль 25, 2013, 14:43
Проблема решена. Покритикуйте:
Код
C++ (Qt)
void MainWindow::bufferButtonSave()
{
   QClipboard *clipboard = QApplication::clipboard();
   QString originalText = clipboard->text();
 
   originalText.replace(QRegExp("\\W"), " ");
   originalText.replace(QRegExp("\\d"), " ");
 
       QTextStream fileStream( & originalText );
       QString itemStr, trimmedStr;
       QStringList itemList;
 
       QString nnn;
 
       textory.clear();
 
       do
       {
           // Пословно
           fileStream >>(itemStr);
           // Построчно
//            itemStr = fileStream.readLine();
 
           trimmedStr = itemStr.trimmed();
//  Убираем пустышку
           if( trimmedStr.isEmpty() )
               continue;
 
           QRegExp rx("\\b(" + trimmedStr + ")\\b");
 
           int coun(0);
           int pos = 0;
           while ((pos = rx.indexIn(originalText, pos)) != -1)
           {
               ++coun;
               ++pos;
           }
 
           nnn.setNum(coun);
 
           trimmedStr = trimmedStr + nnn;
           itemList.prepend( trimmedStr );
 
       } while( !fileStream.atEnd() );
 
       textory.enableAdd( true );
 
          foreach (QString itm, itemList)textory.addItem( Textory::Item( 1, itm ) );
 
       textory.enableAdd( cfg.preferences.storeTextory );
}


Название: Re: Регулярное выражение с QString
Отправлено: Spark от Июль 25, 2013, 15:13
делай trimmed для исходной строки
Типа этого:
Код
C++ (Qt)
   QClipboard *clipboard = QApplication::clipboard();
   QString xt = clipboard->text();
   QString originalText = xt.trimmed();
Не сработало.


Название: Re: Регулярное выражение с QString
Отправлено: m_ax от Июль 25, 2013, 15:40
Проблема решена. Покритикуйте:

Это ерунда какая то.. И критиковать здесь бесполезно( Какой смысл?

Я предлагаю вам написать отдельный класс для анализа текста.
Спроектируйте архитектуру этого класса. Так, чтоб он был самодостаточным, интуитивно понятным (даже младенцу).
Чтобы была возможность задавать ему опции для сравнения строк (с учётом регистра, без и т.д.)

И напишите его без использования Qt.)

Тогда в этом будет смысл и польза для вас.. А так это просто переливание из пустого в порожнее..(

Удачи)
 


Название: Re: Регулярное выражение с QString
Отправлено: Spark от Июль 25, 2013, 15:50
Проблема решена. Покритикуйте:

Это ерунда какая то.. И критиковать здесь бесполезно( Какой смысл?

Я предлагаю вам написать отдельный класс для анализа текста.
Спроектируйте архитектуру этого класса. Так, чтоб он был самодостаточным, интуитивно понятным (даже младенцу).
Чтобы была возможность задавать ему опции для сравнения строк (с учётом регистра, без и т.д.)

И напишите его без использования Qt.)

Тогда в этом будет смысл и польза для вас.. А так это просто переливание из пустого в порожнее..(

Удачи)
  
Вижу вы тоже желаете меня в игнор записать :).

Поясняю. Не ради забавы я пишу эту часть программки. У меня вполне конкретные цели. И раз я в ветке для начинающих и на форуме QT, то наверное стоит критиковать не мое отношение к чистому коду, а сам код написанный с использованием QT.

P.S. Я не считаю себя программистом, тем более профи. Я обучаюсь и хотел бы немного стать программистом, ну а если повезет то и профи.


Название: Re: Регулярное выражение с QString
Отправлено: m_ax от Июль 25, 2013, 16:12

Вижу вы тоже желаете меня в игнор записать :).

Да зачем мне вас в чс заносить? Я никого не туда не заношу.. Дело не в этом(

Цитировать
Поясняю. Не ради забавы я пишу эту часть программки. У меня вполне конкретные цели.

Шутите? И какие же? Без вашего сегодняшнего кода и программы, завтра во вселенной нарушится равновесие и мир превратится в хаус?)

Цитировать
И раз я в ветке для начинающих и на форуме QT, то наверное стоит критиковать не мое отношение к чистому коду, а сам код написанный с использованием QT.

А я и не критикую чистоту вашего кода, заметьте.
Для меня более важен сам подход, образ мысли, то, как спроектирована архитектура. Вот вы говорите, что новичёк и т.д. тогда для вас гораздо более первостепенным - учиться мыслить категориями языка, а не зарываться в частности (Qt - это тоже частности).  Я об этом уже говорил. Вы сейчас мыслите на процедурном уровне и используя при этом метод тыка.. 

Вы просите критики, но совершенно слепы к  ней( Может вам не критика нужна, а внимание и похвала?) Мм?)
А вообще, для хорошей конструктивной критики нужно тоже дорасти, делая при этом со своей стороны усилия..

Я вам дал дельный совет, но вы его восприняли в штыки.. О чём это говорит?

 

   

 



 


Название: Re: Регулярное выражение с QString
Отправлено: Spark от Июль 25, 2013, 16:36
- Мне нравится метод тыка в обучении. Совместно с другими методами он приводит к результату гораздо быстрее. Даже не хочу и не буду на эту тему спорить. Плавали не раз, знаем.
- Я не стремлюсь к тому, что бы меня похвалили, тем более я понимаю, что этого не будет и тем более моя манера общения наоборот может вызывать раздражение. Но комплекса неполноценности у меня нет и другим того же желаю. Код на показ выставляю только с одной единственной целью, что бы оценили его практичность и критиковали по делу (по поводу кода), записываю и пытаюсь либо сразу оптимизировать, либо позже. Пока же очерчиваю круг задач.
- Мир не рухнет. Но когда работа будет готова и я решу показать ее, тогда возможно поймете почему я поступаю так как поступаю сейчас...
- Надоело уговаривать программиста, что бы он каждый пункт очередной фишки выполнил. Теперь все, что задумал реализовываю сам с точки зрения пользователя.

P.S. Ваш совет я не воспринял в штыки и прекрасно его понимаю. Но к моей основной цели он имеет второстепенное значение и не ускорит ее осуществление, отбросит и в конце концов работа будет заброшена. И та часть мира которая ждала появления моей работы будет огорчена :).


Название: Re: Регулярное выражение с QString
Отправлено: m_ax от Июль 25, 2013, 16:58
P.S. Ваш совет я не воспринял в штыки и прекрасно его понимаю. Но к моей основной цели он имеет второстепенное значение и не ускорит ее осуществление, отбросит и в конце концов работа будет заброшена. И та часть мира которая ждала появления моей работы будет огорчена :).

К несчастью для вас - это типичное заблуждение(
Наивно подходить к делу не освоив инструмент и сам язык на концептуальном уровне и при этом ожидать какие то дивиденды..
Тот путь, что вы избрали, скорее и приведёт к огорчению той части мира ваших пользователей и вас самого, в частности..

Но дело, конечно, ваше) Не буду спорить)
     


Название: Re: Регулярное выражение с QString
Отправлено: Alex Custov от Июль 25, 2013, 17:00
- Мне нравится метод тыка в обучении. Совместно с другими методами он приводит к результату гораздо быстрее.

Забивать шурупы тоже гораздо быстрее.


Название: Re: Регулярное выражение с QString
Отправлено: Spark от Июль 25, 2013, 17:28
Ok! По делу. Подскажите как лучше привести текст к нижнему регистру?


Название: Re: Регулярное выражение с QString
Отправлено: Alex Custov от Июль 25, 2013, 17:30
Ok! По делу. Подскажите как лучше привести текст к нижнему регистру?

QString::toLower(), всё описано в документации.


Название: Re: Регулярное выражение с QString
Отправлено: Spark от Июль 25, 2013, 17:43
Ok! По делу. Подскажите как лучше привести текст к нижнему регистру?

QString::toLower(), всё описано в документации.
Спасибо.
Вторая часть совета как раз и есть метод проб и ошибок. Забавно то, что большинство тех кто отрицает метод проб и ошибок, как раз в первую отправляют заниматься этим делом :), причем в худшем проявлении этого метода.
Но про метод проб и ошибок я не в буквальном смысле писал. Метод научного тыка - общепризнанный метод вообще как таковой. Иначе бы не имели того, что сейчас имеем.
Ох в очередной раз пустились во флуд :).

P.S. Кстати, никакой выгоды для себя я не собираюсь извлекать. Моя работа держится на энтузиазме. Мне это нравится и возможно моя работа кому то пригодится.


Название: Re: Регулярное выражение с QString
Отправлено: m_ax от Июль 25, 2013, 18:00
Спасибо.
Вторая часть совета как раз и есть метод проб и ошибок. Забавно то, что большинство тех кто отрицает метод проб и ошибок, как раз в первую отправляют заниматься этим делом :), причем в худшем проявлении этого метода.
Но про метод проб и ошибок я не в буквальном смысле писал. Метод научного тыка - общепризнанный метод вообще как таковой. Иначе бы не имели того, что сейчас имеем.
Ох в очередной раз пустились во флуд :).

А никто и не говорит, что метод проб и ошибок - это зло)
Печально, когда процесс познания слепо основывается только на нём( И игнорируется опыт и знания накопленные до этого( 


Название: Re: Регулярное выражение с QString
Отправлено: kambala от Июль 25, 2013, 18:48
делай trimmed для исходной строки
Типа этого:
Код
C++ (Qt)
   QClipboard *clipboard = QApplication::clipboard();
   QString xt = clipboard->text();
   QString originalText = xt.trimmed();
Не сработало.

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

общая критика кода: он ужасен т.к. просто читая его очень трудно понять что там происходит (во всяком случае мне).

2m_ax: бессмысленно сотрясаешь воздух. Spark будет делать так, как ему хочется (методом научного тыка), а не так, как хорошо, в чем можно было убедиться по его предыдущим задачам и решениям.

2Spark: а ты никогда не задумывался: что если кто-то другой (даже не обязательно программист, а другой обычный пользователь с энтузиазмом) захочет что-то поменять в твоем коде? ты б хоть комментарии там оставлял какие-то.


Название: Re: Регулярное выражение с QString
Отправлено: Spark от Июль 25, 2013, 19:16
Парни! Я ведь выкладываю обычно готовый код и как правило рабочий. Неужели вы думаете, что это можно делать основываясь только на методе проб и ошибок? Естественно пользуюсь справочниками, книгами, видеоматериалом, вас спрашиваю, пользуюсь поиском и изучаю чужой код, кто как решал подобное. Но в любом случае на долю проб и ошибок уходит львиная доля работы. По моему достаточно серьезные задачи перед собой ставлю после двух месяцев обучения. Я слабый ученик? Ну что ж какой есть, остальные наверное после родов сразу на двух языках говорить умели.

я лично вообще не вижу разницы с предыдущим кодом, разве что только если начну построчно сравнивать.
В общем то подписал:
Код
C++ (Qt)
           trimmedStr = itemStr.trimmed();
//  Убираем пустышку
           if( trimmedStr.isEmpty() )
               continue;

Код ужасен. Ну не слово в слово, не буква в букву, но ведь работает :).
Однако с точки зрения техники исполнения предложений больше не было, кроме того варианта, что раскритиковали. Сделал только с учетом ваших поправок. Значит достаточно нормально. Остальное буду править по мере осознания как можно лучше.


Название: Re: Регулярное выражение с QString
Отправлено: Spark от Июль 26, 2013, 05:15
Необходимо разделить частотный список по языкам. Английский текст не сложно удалить:
Код
C++ (Qt)
   QClipboard *clipboard = QApplication::clipboard();
   QString originalText = clipboard->text();
 
   originalText = originalText.toLower();
   originalText.replace(QRegExp("[a-z]"), "");
Русский не удается удалить:
Код
C++ (Qt)
   originalText.replace(QRegExp("[а-я]"), "");
Как поступить?


Название: Re: Регулярное выражение с QString
Отправлено: Majestio от Июль 26, 2013, 06:19
Смешались в кучу кони, люди, и залпы тысячи орудий слились в протяжный вой (С)

Уважаемый топикстартер, задумываясь о реализации, вы бы сперва удосужились выполнить два важных шага:

1) постановка задачи
2) описание алгоритма

Публикуя в первом сообщении вопрос, и приведя п.1-2, был бы разговор более предметным. Прокачивать телепатию - дело неблагодарное.

По сути вопроса...

Ответ одному из участников обсуждения: "Алгоритм в один проход более оптимален" - смелое, но в полном обобщении - бредовое утверждение. Все зависит от накладных расходов, требуемых для реализации алгоритма. Если придется для "рассовой чистоты" (один проход) строить Китайскую Стену, то я против.

Как я понял, смысл задачи - разбить текст на слова, подсчитать вхождения? Если я правильно понял, то QString::split - разбивать замечательно умеет. Таким образом, вам придется только определиться с набором символов-разделителей. Обратите внимание на документацию:

Код:
QString str;
QStringList list;

str = "Some  text\n\twith  strange whitespace.";
list = str.split(QRegExp("\\s+"));
// list: [ "Some", "text", "with", "strange", "whitespace." ]

В примере выше в качестве разделителей используются "пробельные" символы (пробел, табуляция, перевод строки, возврат каретки). Модифицируйте это под себя - добавьте знаки пунктуации ... и сделайте разбиение вашего текста одним оператором. Получите QStringList, содержащий весть набор слов из текста.

Далее пробегайте по списку и строите частоты, частоты имхо, удобно хранить в QMap<QString, int>. Таким образом код можно переписать в виде:

Код:
QString Text = tr("Это, входной: текст");
QStringList List = Text.split(QRegExp("\\s+"),QString::SkipEmptyParts);
QMap <QString, int> MyMap;
foreach (QString Item, List) MyMap[Item] = (MyMap.contains(Item)) ? MyMap[Item]+1 : 1;

Замечания:
1. Возможно QMap - не самое быстрое решение. Читаем тут (http://habrahabr.ru/post/170017/). Эксперементируем.
2. Возможно последнюю строчку можно реализовать и так: foreach (QString Item, List) MyMap[Item]++; я не пробовал, не совсем помню все ньюансы работы с контейнерами

Вобщем как-то так.


Название: Re: Регулярное выражение с QString
Отправлено: Old от Июль 26, 2013, 08:11
Ответ одному из участников обсуждения: "Алгоритм в один проход более оптимален" - смелое, но в полном обобщении - бредовое утверждение.
Что значит в "полном обобщении"? И почему оно бредовое? :)

Все зависит от накладных расходов, требуемых для реализации алгоритма.
Накладные расходы минимальные, реализовать алгоритм в один проход очень просто. Поэтому, рекомендовать реализацию в два прохода просто глупо. Тем более повторно.




Название: Re: Регулярное выражение с QString
Отправлено: Majestio от Июль 26, 2013, 08:48
Ответ одному из участников обсуждения: "Алгоритм в один проход более оптимален" - смелое, но в полном обобщении - бредовое утверждение.
Что значит в "полном обобщении"? И почему оно бредовое? :)

Не все алгоритмы линейны. Значит утверждение - носит частный характер.
Бредовое - потому как сделано без оглядки на полную постановку задачи, которой, увы, так и не прозвучало.

Все зависит от накладных расходов, требуемых для реализации алгоритма.
Накладные расходы минимальные, реализовать алгоритм в один проход очень просто. Поэтому, рекомендовать реализацию в два прохода просто глупо. Тем более повторно.

Регекспы - мощнейшее средство обработки текста. А в Qt оно еще работает и с кодировками. Реализовать парсинг текста с помощью регэкспов - на порядок проще, нежели последовательным сканированием и вычленением. Следовательно изобретать велосипед (сканер) бессмысленно при наличии готовых удобных средств. В этом и смысл фреймворка - экономить время кодинга & code reuse.

Если чуть-чуть изменить постановку задачи, последовательный парсинг вырастет в монстра.

Пример с потолка - вычислить "веса" слов по формуле:

Вес_слова = количество повторений*суммарное_количество_слов_стоящих_после.

Попробуйте построить однопроходной алгоритм (рекурсию не предлагать, стек ограничен, работаем с кучей).


Название: Re: Регулярное выражение с QString
Отправлено: Old от Июль 26, 2013, 09:00
Не все алгоритмы линейны. Значит утверждение - носит частный характер.
Какое утверждение, причем здесь линейность алгоритмов?

Бредовое - потому как сделано без оглядки на полную постановку задачи, которой, увы, так и не прозвучало.
Какую полную постановку? ТС нужно посчитать частоты вхождения слов, это полная постановка задачи.

Вот этот поток сознания к чему вообще? :)
Регекспы - мощнейшее средство обработки текста. А в Qt оно еще работает и с кодировками. Реализовать парсинг текста с помощью регэкспов - на порядок проще, нежели последовательным сканированием и вычленением. Следовательно изобретать велосипед (сканер) бессмысленно при наличии готовых удобных средств. В этом и смысл фреймворка - экономить время кодинга & code reuse.

Если чуть-чуть изменить постановку задачи, последовательный парсинг вырастет в монстра.

Пример с потолка - вычислить "веса" слов по формуле:

Вес_слова = количество повторений*суммарное_количество_слов_стоящих_после.

Попробуйте построить однопроходной алгоритм (рекурсию не предлагать, стек ограничен, работаем с кучей).
Нам нужно решить конкретную задачу, ее легко можно решить в один проход, причем совсем без регулярных выражений. Все. :)


Название: Re: Регулярное выражение с QString
Отправлено: Majestio от Июль 26, 2013, 09:19
Какую полную постановку? ТС нужно посчитать частоты вхождения слов, это полная постановка задачи.
Нам нужно решить конкретную задачу, ее легко можно решить в один проход, причем совсем без регулярных выражений. Все. :)

Вы завели разговор о "легкости" и "оптимальности". Я утверждаю, что с помощью регэкспов это сделать легче (кодить меньше) и оптимальнее (в данном случае критерием может быть только наглядность, ибо скорость исполнения зависит от входных данных - каков текст, что считать разделителями). Хотите поспорить? Давайте на практике попробуем?

Постановка задачи

Входной текст - латинские символы алфавита+русские, кодировка UTF8. Разделителями считаем - пробельные символы (пробел, табуляция, перевод строки, возврат каретки), точку, запятую, двоеточие, точка с запятой, тире в виде минуса, открывающую и закрывающую скобки.

Моя "неоптимальная реализация":

Код:
QTextCodec *Сodec = QTextCodec::codecForName("UTF-8");
QTextCodec::setCodecForLocale(Сodec);
QString Text = tr("Это, входной: текст");
QStringList List = Text.split(QRegExp("[\\s\.,:;-()]+"),QString::SkipEmptyParts);
QMap <QString, int> MyMap;
foreach (QString Item, List) MyMap[Item] = (MyMap.contains(Item)) ? MyMap[Item]+1 : 1;

Покажите ваш оптимальный код. Без кораблей, бороздящих океаны ...


Название: Re: Регулярное выражение с QString
Отправлено: Spark от Июль 26, 2013, 09:46
Итак задача. Взять текст из буфера и составить частотный список:
- Всего слов
- Количество вхождений каждого слова
- Сортировка

Значит в рамках QT и данной функции (bufferButtonSave()) решение никому не нравится?:
Код
C++ (Qt)
void MainWindow::bufferButtonSave()
{
   QClipboard *clipboard = QApplication::clipboard();
   QString originalText = clipboard->text();
   originalText = originalText.toLower();
   originalText.replace(QRegExp("\\W"), " ");
   originalText.replace(QRegExp("\\d"), " ");
 
   // ЭТО НЕ РАБОТАЕТ
   originalText.replace(QRegExp("[а-я]"), "");
 
       QTextStream fileStream( & originalText );
       QString itemStr, trimmedStr;
       QStringList itemList;
       QString countItemString;
       QString fullCountItemString;
 
       int fullCountItem(0);
 
       textory.clear();
 
       do
       {
           // Формируем список пословно
           fileStream >>(itemStr);
 
           trimmedStr = itemStr.trimmed();
           if( trimmedStr.isEmpty() )
               continue;
 
           QRegExp rx("\\b(" + trimmedStr + ")\\b", Qt::CaseInsensitive);
 
           int countItem(0);
           int pos(0);
 
           while ((pos = rx.indexIn(originalText, pos)) != -1)
           {
               ++countItem;
               ++pos;
           }
 
           countItemString.setNum(countItem);
           ++fullCountItem;
 
           trimmedStr = trimmedStr + "\t" + countItemString;
           itemList.prepend( trimmedStr );
 
       } while( !fileStream.atEnd() );
 
       // Выводим список на экран:
 
       textory.enableAdd( true );
 
       fullCountItemString.setNum(fullCountItem);
 
       // СОРТИРУЕМ: РАБОТАЕТ В ПОРЯДКЕ ВОЗРАСТАНИЯ.
       // НАДО1 - В ПОРЯДКЕ УБЫВАНИЯ.
       // НАДО2 - ОТСОРТИРОВАТЬ В ПОРЯДКЕ ЧАСТОТНОСТИ.
       qSort(itemList);
 
       foreach (QString itm, itemList)textory.addItem( Textory::Item( 1, itm ) );
 
       // Заголовок спсика:
ui.textoryWidget->getTextoryLabel().setText( "Frequency list (" + fullCountItemString + ")" );
}
Получаем вроде этого:
(http://s019.radikal.ru/i631/1307/f8/a9798a12c650t.jpg) (http://radikal.ru/fp/6307c2f8200c4cc0a06971f2b9a9be4f)
Всеобщее мнение можно сделать более быстрый, надежный алгоритм? Если так, буду думать.
В алгоритме два комментария в верхнем регистре - задачи над которыми сейчас работаю. Если кто захочет помочь, ничего не имею против :).


Название: Re: Регулярное выражение с QString
Отправлено: Igors от Июль 26, 2013, 10:02
Проблема решена. Покритикуйте:
Ну пока плохо. m_ax совершенно прав - Вам не хватает размаха, ковыряетесь в мелочах вместо того чтобы видеть конструкцию в целом. Такой подход часто называют "ловлей блох".

Вы добавляете частоту как строку, т.е. просто показываете ее юзеру. Это не по-хозяйски, результаты расчета надо хранить чтобы потом не бегать. Не нужно даже тратить время на размышления типа "а где еще она может понадобиться".

Если Вы упоминаете о скорости - то зачем Вы делаете квадратичный алгоритм? Ведь просмотр всей исходной строки (потенциально большой) для каждого слова - это просто глупость. Гораздо быстрее и проще сначала получить слова и оперировать уже с ними.

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

Код ужасен. Ну не слово в слово, не буква в букву, но ведь работает :).
Однако с точки зрения техники исполнения предложений больше не было,
Неправда, были. Работать может и работает, но на последнем издыхании - запас прочности нулевой. Следующая простейшая задача русский/английский уже вызывет большие трудности. А было бы по уму, со словами - достаточно добавить всего одну ф-цию, напр GetWordLang(). Вместо этого опять чего-то риплейсите с тем regexp который здесь ни пришей - ни пристегни.


Название: Re: Регулярное выражение с QString
Отправлено: Spark от Июль 26, 2013, 10:16
Результаты расчета хранятся в текстовом файле. Формат удобен для Excel:
Слово табуляция частота.
Информацию сложно вытащить в случае необходимости?

По поводу недостатка опыта. Однако очевидно, что что бы он пришел недостаточно пары месяцев. Вы считаете, что я решаю тривиальные задачи для новичка? По поводу UI и расчетов. Меня интересует реализация самой функции. Организационные вопросы меня не интересуют. Со временем само придет.

Ok! Попробую разобраться с другим алгоритмом.


Название: Re: Регулярное выражение с QString
Отправлено: Igors от Июль 26, 2013, 11:03
Результаты расчета хранятся в текстовом файле ...
Не спорьте и не пререкайтесь со старшими. Вы всегда можете "пойти своим путем", эта возможность никуда не убежит  :)

Сортируем по частоте (по убыванию)

Код
C++ (Qt)
struct CFreq {
CFreq( int count = 1,  const QString * str = 0 ) : mCount(count), mStr(str) {}
bool operator < ( const CFreq & sec ) const { return mCount > sec.mCount; }
 
int mCount;
const QString * mStr;
};
 
typedef QMap <QString. int> TMapStr;
TMapStr theMap;
... // заполняем мапу - см выше
 
// заполняем вектор
QVector <CFreq> theFreq;
for (TMapStr::const_iterator it = theMap.begin(); it != theMp.end(); ++it)
theFreq.push_back(CFreq(it->value(), &it->key()));
 
// сортируем
qSort(theFreq.begin(), theFreq.end());
 
// печатаем
for (int i = 0; i < theFreq.size(); ++i)
qDebug() << *theFreq[i].mStr << "\n"
 


Название: Re: Регулярное выражение с QString
Отправлено: Old от Июль 26, 2013, 11:31
Покажите ваш оптимальный код. Без кораблей, бороздящих океаны ...
То, что набросал за 5 минут:
Код
C++ (Qt)
void stat()
{
QString src = "erwerwer ewr werwerwerwerew werwerwe sdfsdfsdf tyutyu\tdsfsdfds+werewrer-ewr";
QString sep = "[ \\t\\n\\r+-]";
QHash<QString, int> hash;
 
QRegExp rx( sep );
 
int start = 0;
int cur = 0;
for(;;)
{
cur = rx.indexIn( src, cur );
QString word = src.mid( start, (cur != -1)? cur - start : -1 );
if( !word.isEmpty() )
{
qDebug() << word;
hash[ word ]++;
}
 
if( cur == -1 )
break;
 
start = ++cur;
}
 
qDebug() << hash;
}
 
Сравните пока с этим, а если будет нужно, я уберу регулярку и тогда вы удивитесь еще больше. :)


Название: Re: Регулярное выражение с QString
Отправлено: m_ax от Июль 26, 2013, 13:50
Я бы всё же написал отдельный класс для этого дела.

И ещё по поводу сплита (QString::split) имхо, это немного не то, когда речь идёт о статистике слов. Сплит задаёт правила для разделителей, а не для самих токенов. В связи с этим split выглядит несколько ущербным по своим возможностям для данной постановки вопроса. Что если я хочу предоставить пользователю следить за статистикой отдельных букв, или слов или только цифр или..

Не знаю как в Qt, но для такой цели в boost'е есть очень удобный regex_iterator (я о том, который входит именно в boost::xpressive, а не в boost::regex)
А одна из фишек xpressive - можно легко задавать варианты поиска с учётом и без учёта регистра. (в boost::regex не нашёл как это можно легко сделать)
  
Короче, я бы накидал такой классик (word_statistics):

Код
C++ (Qt)
#include <iostream>
#include <boost/xpressive/xpressive.hpp>
#include <boost/algorithm/string/case_conv.hpp>
#include <string>
#include <unordered_map>
 
class word_statistics
{
public:
   typedef std::string string_type;
   typedef std::unordered_map<string_type, unsigned> hash_type;
   typedef typename hash_type::size_type size_type;
   typedef typename hash_type::const_iterator const_iterator;
 
   word_statistics(const string_type & source) : m_source(source), m_total_count(0) {}
 
   void compile(const string_type & expr, bool icase = false) {
       using namespace boost::xpressive;
       sregex e = (icase) ? sregex::compile(expr, regex_constants::icase) : sregex::compile(expr);
       sregex_iterator it(m_source.begin(), m_source.end(), e);
       sregex_iterator end;
       m_hash.clear();
       for (m_total_count = 0; it != end; ++it, ++m_total_count) {
           if (icase)
               ++m_hash[boost::algorithm::to_lower_copy(it->str(0))];
           else
               ++m_hash[it->str(0)];
       }
   }
 
   size_type total_count() const { return m_total_count; }
   size_type size() const { return m_hash.size(); }
   const_iterator begin() const { return m_hash.begin(); }
   const_iterator end() const { return m_hash.end(); }
 
private:
   string_type m_source;
   size_type m_total_count;
   hash_type m_hash;
};
 
int main()
{
 
   std::string str("text1, text2 and a lot of TextT 3");
   word_statistics word_stat(str);
 
   word_stat.compile("(\\d+)", true);
   std::cout << "only digit:\n";
   for (auto s : word_stat) {
       std::cout << s.first << " = " << s.second << std::endl;
   }
   std::cout << "total count = " << word_stat.total_count() << "\n\n";
 
   std::cout << "only word:\n";
   word_stat.compile("([a-zA-Z]+)", false);
   for (auto s : word_stat) {
       std::cout << s.first << " = " << s.second << std::endl;
   }
   std::cout << "total count = " << word_stat.total_count() << "\n\n";
 
   std::cout << "only [a e t]:\n";
   word_stat.compile("([aet])", true);
   for (auto s : word_stat) {
       std::cout << s.first << " = " << s.second << std::endl;
   }
   std::cout << "total count = " << word_stat.total_count() << "\n\n";
 
   return 0;
}
 


и результаты будут такие:
Код
Bash
source = text1, text2 and a lot of TextT 3
 
only digit:
1 = 1
2 = 1
3 = 1
total count = 3
 
only word:
TextT = 1
of = 1
lot = 1
a = 1
and = 1
text = 2
total count = 7
 
only [a e t]:
e = 3
a = 2
t = 8
total count = 13
 

Да, ну ещё бы добавил возможность задавать сортировку и установку локали..


Название: Re: Регулярное выражение с QString
Отправлено: Spark от Июль 26, 2013, 13:56
Собрал так. Критикуйте:
Код
C++ (Qt)
void MainWindow::bufferButtonSave()
{
   QClipboard *clipboard = QApplication::clipboard();
   QString originalText = clipboard->text();
   QString countItemFullString;
   QString countItemString;
   QStringList itemList;
   int countItem(0);
   int countItemFull(0);
 
   originalText = originalText.toLower();
   originalText.replace(QRegExp("\\W"), " ");
   originalText.replace(QRegExp("\\d"), " ");
   // ЗАДАЧА1: ЭТО НЕ РАБОТАЕТ
   originalText.replace(QRegExp("[а-я]"), "");
 
       textory.clear();
 
       itemList = originalText.split(QRegExp("\\s+"),QString::SkipEmptyParts);
       QMap <QString, int> frequencyMap;
       foreach (QString Item, itemList) frequencyMap[Item] = (frequencyMap.contains(Item)) ? frequencyMap[Item]+1 : 1;
 
       textory.enableAdd( true );
 
       QMapIterator<QString,int> Iter(frequencyMap);
       while(Iter.hasNext())
       {
           Iter.next();
           countItem = Iter.value();
           countItemString.setNum(countItem);
           countItemFull = countItemFull + countItem;
           // ЗАДАЧА2: ОРГАНИЗОВАТЬ ВЫВОД В ПОРЯДКЕ ЧАСТОТНОСТИ
           textory.addItem( Textory::Item( 1, Iter.key() + "\t" + countItemString) );
       }
       countItemFullString.setNum(countItemFull);
       ui.textoryWidget->getTextoryLabel().setText( "Frequency list (" + countItemFullString + ")" );
}
Пока, что решает только те задачи которые решал первый вариант. Поставленные на сегодня задачи не решал. Выделены комментариями в верхнем регистре.

P.S. Будем обдумывать новые предложения.


Название: Re: Регулярное выражение с QString
Отправлено: Igors от Июль 26, 2013, 14:34
Код
C++ (Qt)
       foreach (QString Item, itemList) frequencyMap[Item] = (frequencyMap.contains(Item)) ? frequencyMap[Item]+1 : 1;
 
Просто
Код
C++ (Qt)
       foreach (QString Item, itemList) ++frequencyMap[Item];
 
Если элемента не было, он вставится и value будет = 0, надо только сделать ++

В целом заметно лучше, снести работающий говнокод всегда трудно - но победили, молодец. Но каша UI + расчеты к сожалению остается. Вы делаете как будто у Вас только одна задача - это маловерятно, реально нужно будет показать и по порядку, и по частоте и еще как-то (напр только английский или наоборот). Выделите "сущность", напр
Код
C++ (Qt)
struct CDataBlock  {
QString mSource;   // строка - первоисточник
QStringList mWords;  // список слов
QMap <QString, int> mFreqMap;  // частотная карта
};
 
Возможно сделать экземпляр этого класса членом MainWindow. Дальше начинаете обдумывать - а какие методы этому классу нужны? Ну очевидно конструктор принимающий строку (mSource). Хорошо, что еще? А почему бы не сделать все "выдачи" внутри этого класса? (вместо того чтобы гадить в UI) Напр

Код
C++ (Qt)
QStringList CDataBlock::GetByOrder( void ) const; // выдаем строки по порядку с приклееной частотой
QStringList CDataBlock::GetByFrequency( bool ascending ) const; // выдаем строки по частотt

и.т.д.

Да, возможен такой поворот событий - потребовалось подсветить все слова с частотой напр > 3 в исходном тексте. Ну типа проверка архитектуры на вшивость :) Что бум делать?


Название: Re: Регулярное выражение с QString
Отправлено: Spark от Июль 26, 2013, 15:16
В целом заметно лучше, снести работающий говнокод всегда трудно - но победили, молодец. Но каша UI + расчеты к сожалению остается. Вы делаете как будто у Вас только одна задача - это маловерятно, реально нужно будет показать и по порядку, и по частоте и еще как-то (напр только английский или наоборот).
На самом деле не очень понимаю, что не так с UI и кодом.
Есть UI_виджет - типа окна списка. Этот виджет входит в главное окно и в нем открывается список.
В maiwindow.cc прописал кнопку и навесил вот эту функцию расчета частотности.
Понимаю, что наверное функцию надо было вынести в отдельный листинг? В общем то она маленькая (пока еще).
Хорошо осознаем со временем и исправим. Стиль работы постепенно должен выработаться.

На самом деле в первом приближении в задачи частотника входит:
- Общее количество слов (сделано).
- Оригинальных слов (сделано).
- Вхождение каждого слова (сделано).
Это уже не плохо.
Надо сделать:
- Выбор языка.
- Ограничение по минимальному и максимальному количеству букв в слове, по количеству повторяемости слова.
- Сортировка по: алфавиту, количеству, без сортировки.
Первый вариант кода делал без сортировки. Т.е. ставил слова в порядке первого вхождения, что было хорошо. Второй вариант, не так делает, а жаль.
Это общий круг текстового анализа. Довольно стандартный.

Вторая стадия будет заключаться в более глубоком анализе текста. Надеюсь осилю.


Название: Re: Регулярное выражение с QString
Отправлено: Spark от Июль 26, 2013, 16:42
Выделите "сущность", напр
Код
C++ (Qt)
struct CDataBlock  {
QString mSource;   // строка - первоисточник
QStringList mWords;  // список слов
QMap <QString, int> mFreqMap;  // частотная карта
};
 
Возможно сделать экземпляр этого класса членом MainWindow. Дальше начинаете обдумывать - а какие методы этому классу нужны? Ну очевидно конструктор принимающий строку (mSource). Хорошо, что еще? А почему бы не сделать все "выдачи" внутри этого класса? (вместо того чтобы гадить в UI) Напр

Код
C++ (Qt)
QStringList CDataBlock::GetByOrder( void ) const; // выдаем строки по порядку с приклееной частотой
QStringList CDataBlock::GetByFrequency( bool ascending ) const; // выдаем строки по частотt

и.т.д.
В целом смысл ясен. Но вот опять же опыта маловато, что бы с легкостью это делать. Конечно в идеале раз увидеть как это последовательно делается. Либо более долгий путь ковырять исходники примеров и постепенно выстраивать свою структуру. Пока протаптываем дорожки и бегаем по проторенным. Как нибудь и эту протопчим :).


Название: Re: Регулярное выражение с QString
Отправлено: Spark от Июль 26, 2013, 18:21
Как расположить в алфавитном порядке разобрался:
Код
C++ (Qt)
       QMapIterator<QString,int> Iter(frequencyMap);
       Iter.toBack();
       while(Iter.hasPrevious())
       {
           Iter.previous();
           countItem = Iter.value();
           countItemString.setNum(countItem);
           countItemFull = countItemFull + countItem;
           // ЗАДАЧА2: ОРГАНИЗОВАТЬ ВЫВОД В ПОРЯДКЕ ЧАСТОТНОСТИ
           textory.addItem( Textory::Item( 1, Iter.key() + "\t" + countItemString) );
       }
Надо понять как расположить в порядке частотности и каким образом оставить нужный язык с списке.
Любой помощи рад.


Название: Re: Регулярное выражение с QString
Отправлено: Old от Июль 26, 2013, 19:08
Еще один "добрый" совет? :)

Код
C++ (Qt)
// заполняем вектор
QVector <CFreq> theFreq;
for (TMapStr::const_iterator it = theMap.begin(); it != theMp.end(); ++it)
theFreq.push_back(CFreq(it->value(), &it->key()));
 

Сколько раз будет перераспределяться память и копироваться содержимое вектора (пусть это указатели)?
А ведь количество элементов нам известно заранее, вот и нужно сразу резервировать память, что бы она не фрагментировалась и ненужных копирований не происходило:
Код
C++ (Qt)
// заполняем вектор
QVector <CFreq> theFreq;
theFreq.reserve( theMap.size() );
 


Название: Re: Регулярное выражение с QString
Отправлено: Majestio от Июль 26, 2013, 22:27
Сравните пока с этим, а если будет нужно, я уберу регулярку и тогда вы удивитесь еще больше. :)

Не поленился - сравнил.
Если интересно, смотрите тут (http://majestio.tk/soft/Words.7z) (для Qt 5.0.2).

Ваш код немного подправил (заменил QHash на QMap, просто для уравнивания условий, выкинул дебаги).
Итоги таковы:

1) Ваш код работает на 1/5 быстрее моего
2) Мой код компактнее вашего практически в 2 раза

Вопрос 1: как будем делить "оптимальность"? Если критерии равнозначны ... ну сами понимаете.
Вопрос 2: я тестировал на 1000 итерациях произвольной книжки - на моем компе это заняло около 7 минут, если речь идет об одной итерации, важно 0.5 сек или 0.4???

Считаю ваше утверждение об "оптимальности" несколько натянутым. Если в общем зачете, вы - отстаете. Если будем под оптимальностью понимать исключительно скорость - тогда я только за asm, только за хардкор!  ;D


Название: Re: Регулярное выражение с QString
Отправлено: Majestio от Июль 26, 2013, 22:41
ЗЫ: Чет мой провайдер hostinger.ru зашалил ... восстановится, сможете тестовый проект качнуть.


Название: Re: Регулярное выражение с QString
Отправлено: Old от Июль 26, 2013, 22:50
1) Ваш код работает на 1/5 быстрее моего
А у меня другие результаты:
8 ms против 28 ms - это если использовать именно QHash как я и писал у себя или
15 ms против 28 ms - это если "уравнивать условия" по вашему.
О каких 1/5 идет речь?


Название: Re: Регулярное выражение с QString
Отправлено: Old от Июль 26, 2013, 22:56
Вот тест для 100 итераций:
Код
C++ (Qt)
#include <QRegExp>
#include <QStringList>
#include <QFile>
#include <QTime>
#include <QDebug>
 
int main( int argc, char *argv[] )
{
QFile in( "test.txt" );
if( !in.open( QIODevice::ReadOnly ) )
{
qWarning( "Test file not found." );
return 1;
}
 
const int num_iter = 100;
QString src = QString::fromUtf8( in.readAll() );
 
QHash<QString, int> hash;
QMap <QString, int> MyMap;
 
QTime tm;
tm.start();
 
for( int i = 0; i < num_iter; ++i )
{
int start = 0;
int cur = 0;
QRegExp rx( "[\\s\\.,:;-()]+" );
for(;;)
{
cur = rx.indexIn( src, cur );
QString word = src.mid( start, (cur != -1)? cur - start : -1 );
if( !word.isEmpty() )
hash[ word ]++;
 
if( cur == -1 )
break;
 
start = ++cur;
}
}
 
qDebug() << tm.elapsed() << hash.size();
 
tm.start();
 
for( int i = 0; i < num_iter; ++i )
{
QStringList List = src.split(QRegExp("[\\s\\.,:;-()]+"),QString::SkipEmptyParts);
foreach (QString Item, List) MyMap[Item] = (MyMap.contains(Item)) ? MyMap[Item]+1 : 1;
}
 
qDebug() << tm.elapsed() << MyMap.size();
 
return 0;
}
 

А вот это на вашей книге (первое число время, второе количество слов в коллекции):
Цитировать
5060 15118
22555 15118
Сколько там получается... быстрее почти в 4,5 раза. А то 1/5... :)

По поводу разного расхода памяти вы сами знаете или нужны пояснения? :)


Название: Re: Регулярное выражение с QString
Отправлено: Majestio от Июль 26, 2013, 23:09
Вот тест для 100 итераций:

Вы регэкспы уравняйте, это тоже существенно))


Название: Re: Регулярное выражение с QString
Отправлено: Old от Июль 26, 2013, 23:12
Вы регэкспы уравняйте, это тоже существенно))
Читайте выше, все уровнял. ;)
И даже результаты можно посмотреть.

А если от регулярки отказаться, то будет совсем грустно. И это с огромным оверхедом по памяти в вашем варианте.


Название: Re: Регулярное выражение с QString
Отправлено: Majestio от Июль 26, 2013, 23:31
Вы регэкспы уравняйте, это тоже существенно))
Читайте выше, все уровнял. ;)
И даже результаты можно посмотреть.

А если от регулярки отказаться, то будет совсем грустно. И это с огромным оверхедом по памяти в вашем варианте.

Взял крайний ваш код (в свой код всунул ваш расчет и вывел в таблицу) - у меня он (ваш) не парсит напрочь, выдает только одну строку.
Если вы не против - я кину исходник, проверьте, подправьте. Все пояснения если чего - с меня)

Это тут - http://majestio.tk/soft/Words-2.7z (http://majestio.tk/soft/Words-2.7z)


Название: Re: Регулярное выражение с QString
Отправлено: Old от Июль 26, 2013, 23:40
Если вы не против - я кину исходник, проверьте, подправьте. Все пояснения если чего - с меня)
Лучше я выложу свой проект.


Название: Re: Регулярное выражение с QString
Отправлено: Majestio от Июль 27, 2013, 00:04
Если вы не против - я кину исходник, проверьте, подправьте. Все пояснения если чего - с меня)
Лучше я выложу свой проект.
Оке, завтра гляну. Там результаты выводятся или только код парсинга?


Название: Re: Регулярное выражение с QString
Отправлено: Old от Июль 27, 2013, 09:47
Немного изменил тест. Теперь коллекция (hash/map) создается и заполняется каждый проход + добавил вывод коллекций для utf8 терминалов.

Код
C++ (Qt)
#include <QRegExp>
#include <QStringList>
#include <QFile>
#include <QTextStream>
#include <QTextCodec>
#include <QTime>
#include <QDebug>
 
template<typename Container>
void dump( const Container &c )
{
       QTextStream out( stdout );
       out.setCodec( QTextCodec::codecForName( "UTF8" ) );
 
       for( typename Container::ConstIterator it = c.constBegin(); it != c.constEnd(); ++it )
               out << "(" << it.key() << ", " << it.value() << ")";
       out << '\n';
}
 
int main( int argc, char *argv[] )
{
       QFile in( "test.txt" );
       if( !in.open( QIODevice::ReadOnly | QIODevice::Text ) )
       {
               qWarning( "Test file not found." );
               return 1;
       }
 
       const int num_iter = 100;
       QString src = QString::fromUtf8( in.readAll() );
 
       QTime tm;
 
       tm.start();
       for( int i = 0; i < num_iter; ++i )
       {
               QHash<QString, int>     hash;
               int start = 0;
               int cur = 0;
               QRegExp rx( "[\\s\\.,:;-()]+" );
               for(;;)
               {
                       cur = rx.indexIn( src, cur );
                       QString word = src.mid( start, (cur != -1)? cur - start : -1 );
                       if( !word.isEmpty() )
                               hash[ word ]++;
 
                       if( cur == -1 )
                               break;
 
                       start = ++cur;
               }
//              dump( hash );
       }
       qDebug() << tm.elapsed();
 
       tm.start();
       for( int i = 0; i < num_iter; ++i )
       {
               QMap <QString, int> MyMap;
               QStringList List = src.split(QRegExp("[\\s\\.,:;-()]+"),QString::SkipEmptyParts);
               foreach (QString Item, List) MyMap[Item] = (MyMap.contains(Item)) ? MyMap[Item]+1 : 1;
//              dump( MyMap );
       }
       qDebug() << tm.elapsed();
 
       return 0;
}
 

В релизе тест показывает, что первый вариант в два раза быстрее второго. И жрет в два раза меньше памяти. Что я и ожидал. :)


Название: Re: Регулярное выражение с QString
Отправлено: Majestio от Июль 27, 2013, 11:47
Немного изменил тест. Теперь коллекция (hash/map) создается и заполняется каждый проход + добавил вывод коллекций для utf8 терминалов.

Код
C++ (Qt)
#include <QRegExp>
#include <QStringList>
#include <QFile>
#include <QTextStream>
#include <QTextCodec>
#include <QTime>
#include <QDebug>
 
template<typename Container>
void dump( const Container &c )
{
       QTextStream out( stdout );
       out.setCodec( QTextCodec::codecForName( "UTF8" ) );
 
       for( typename Container::ConstIterator it = c.constBegin(); it != c.constEnd(); ++it )
               out << "(" << it.key() << ", " << it.value() << ")";
       out << '\n';
}
 
int main( int argc, char *argv[] )
{
       QFile in( "test.txt" );
       if( !in.open( QIODevice::ReadOnly | QIODevice::Text ) )
       {
               qWarning( "Test file not found." );
               return 1;
       }
 
       const int num_iter = 100;
       QString src = QString::fromUtf8( in.readAll() );
 
       QTime tm;
 
       tm.start();
       for( int i = 0; i < num_iter; ++i )
       {
               QHash<QString, int>     hash;
               int start = 0;
               int cur = 0;
               QRegExp rx( "[\\s\\.,:;-()]+" );
               for(;;)
               {
                       cur = rx.indexIn( src, cur );
                       QString word = src.mid( start, (cur != -1)? cur - start : -1 );
                       if( !word.isEmpty() )
                               hash[ word ]++;
 
                       if( cur == -1 )
                               break;
 
                       start = ++cur;
               }
//              dump( hash );
       }
       qDebug() << tm.elapsed();
 
       tm.start();
       for( int i = 0; i < num_iter; ++i )
       {
               QMap <QString, int> MyMap;
               QStringList List = src.split(QRegExp("[\\s\\.,:;-()]+"),QString::SkipEmptyParts);
               foreach (QString Item, List) MyMap[Item] = (MyMap.contains(Item)) ? MyMap[Item]+1 : 1;
//              dump( MyMap );
       }
       qDebug() << tm.elapsed();
 
       return 0;
}
 

В релизе тест показывает, что первый вариант в два раза быстрее второго. И жрет в два раза меньше памяти. Что я и ожидал. :)


Первый тест мне показал:

31797
49750

Потом я кой чего "уровнял" (регулярка была ошибочной - знак минуса нужно квотить + у себя тоже использовал для справедливости QHash:) ... Результаты:

33844
36297

Так какое нафик в 4 раза?)))))) Ваш код быстрее на 10% ))))
Мой код в два раза меньше.
Какие коэффициенты оптимальности выставим??? ... Если равными - ну сами понимаете ))))

Зы: правленый код тут
Код:
#include <QRegExp>
#include <QStringList>
#include <QFile>
#include <QTextStream>
#include <QTextCodec>
#include <QTime>
#include <QDebug>

template<typename Container>
void dump( const Container &c )
{
        QTextStream out( stdout );
        out.setCodec( QTextCodec::codecForName( "UTF8" ) );

        for( typename Container::ConstIterator it = c.constBegin(); it != c.constEnd(); ++it )
                out << "(" << it.key() << ", " << it.value() << ")";
        out << '\n';
}

int main( int argc, char *argv[] )
{
        QFile in( "C:/Temp/test.txt" );
        if( !in.open( QIODevice::ReadOnly | QIODevice::Text ) )
        {
                qWarning( "Test file not found." );
                return 1;
        }

        const int num_iter = 100;
        QString src = QString::fromUtf8( in.readAll() );

        QTime tm;

        tm.start();
        for( int i = 0; i < num_iter; ++i )
        {
                QHash<QString, int>     hash;
                int start = 0;
                int cur = 0;
                QRegExp rx( "[\\s\\.,:;\\-()]+" );
                for(;;)
                {
                        cur = rx.indexIn( src, cur );
                        QString word = src.mid( start, (cur != -1)? cur - start : -1 );
                        if( !word.isEmpty() )
                                hash[ word ]++;

                        if( cur == -1 )
                                break;

                        start = ++cur;
                }
//              dump( hash );
        }
        qDebug() << tm.elapsed();

        tm.start();
        for( int i = 0; i < num_iter; ++i )
        {
                QHash <QString, int> MyMap;
                QStringList List = src.split(QRegExp("[\\s\\.,:;\\-()]+"),QString::SkipEmptyParts);
                foreach (QString Item, List) MyMap[Item] = (MyMap.contains(Item)) ? MyMap[Item]+1 : 1;
//              dump( MyMap );
        }
        qDebug() << tm.elapsed();

        return 0;
}


Название: Re: Регулярное выражение с QString
Отправлено: Majestio от Июль 27, 2013, 12:03
))))) Добавочка ....

Чуть оптимизировал свой код ...

Вместо:
Код:
foreach (QString Item, List) MyMap[Item] = (MyMap.contains(Item)) ? MyMap[Item]+1 : 1;
Записал:
Код:
foreach (QString Item, List) MyMap[Item]++;

Результаты:
34016
34843

Ваш код быстрее на целых 3%! ))))


Название: Re: Регулярное выражение с QString
Отправлено: m_ax от Июль 27, 2013, 12:27
Ваш код быстрее на целых 3%! ))))

Зато по памяти выигрыш более чем в два раза)

Ладно, чтоб никому не было обидно, привожу сравнение ваших результатов с алгоритмом boost::tokenizer:
Добавил все правки в код в соответствии с последними постами)

Код
C++ (Qt)
#include <QRegExp>
#include <QStringList>
#include <QFile>
#include <QTime>
#include <QDebug>
#include <string>
#include <boost/tokenizer.hpp>
#include <unordered_map>
#include <fstream>
#include <sstream>
 
int main()
{
   QFile in( "test.txt" );
   if( !in.open( QIODevice::ReadOnly | QIODevice::Text ) )
   {
       qWarning( "Test file not found." );
       return 1;
   }
 
   const int num_iter = 100;
   QString src = QString::fromUtf8( in.readAll() );
 
   QTime tm;
   unsigned total = 0;
 
   tm.start();
   for( int i = 0; i < num_iter; ++i )
   {
       QHash<QString, int>     hash;
       int start = 0;
       int cur = 0;
       QRegExp rx( "[\\s\\.,:;\\-()]+" );
       for(;;)
       {
           cur = rx.indexIn( src, cur );
           QString word = src.mid( start, (cur != -1)? cur - start : -1 );
           if( !word.isEmpty() )
               hash[ word ]++;
 
           if( cur == -1 )
               break;
 
           start = ++cur;
       }
       total = hash.size();
   //              dump( hash );
   }
   qDebug() << "Old:\t" << tm.elapsed() << total;
 
   tm.start();
   for( int i = 0; i < num_iter; ++i )
   {
       QHash <QString, int> MyMap;
       QStringList List = src.split(QRegExp("[\\s\\.,:;\\-()]+"),QString::SkipEmptyParts);
       foreach (QString Item, List) MyMap[Item]++;
 
       total = MyMap.size();
   //      dump( MyMap );
   }
   qDebug() << "Majestio:\t" << tm.elapsed() << total;
 
   std::ifstream in_("test.txt");
   if (!in_.is_open()) {
       qWarning( "Test file not found." );
       return 1;
   }
 
   std::ostringstream oss;
   oss << in_.rdbuf();
   std::string source = oss.str();
 
   tm.start();
   for( int i = 0; i < num_iter; ++i )
   {
       std::unordered_map<std::string, unsigned> hash;
       boost::tokenizer<boost::char_separator<char>> tok(source, boost::char_separator<char>(" ,.\r\t\n:;-()"));
       for (auto it = tok.begin(); it != tok.end(); ++it) ++hash[*it];
 
       total = hash.size();
   }
   qDebug() << "m_ax:\t" << tm.elapsed() << total;
 
   return 0;
}
 

И результаты у меня такие (release)
Код
Bash
Old:           15629 15211
Majestio:    17590 15211
m_ax:         9028  15211
 

Хе, хе ;)


Название: Re: Регулярное выражение с QString
Отправлено: Old от Июль 27, 2013, 12:41
Ваш код быстрее на целых 3%! ))))
Не знаю почему у вас такие результаты, но у меня выигрыш примерно 10%, судя по результатам m_ax - у него примерно также.
Про двойной выигрыш по скорости я конечно погорячился (нес чего там :) ), но 10% это тоже не мало, к тому же с памятью проблем нет.


Название: Re: Регулярное выражение с QString
Отправлено: Majestio от Июль 27, 2013, 12:42
Хе, хе ;)

Вот не люблю я буст :-P

Ланна ... Резюме какое?
Берем "среднестатистический" текст. Какая разница для интерактивного режима 0.03сек или 0.02???. Какая разница (например для моего компа) - затратит он 700к памяти или полтора мега, если у меня 8Гб на борту? Остается смотреть на скорость и понятность кодинга. Не? :-P

Для эмпирического "потокового анализатора", как я уже говорил - только асм, только хардкор! :-P



Название: Re: Регулярное выражение с QString
Отправлено: Majestio от Июль 27, 2013, 12:46
А m_ax - мошенник)))) давай на регулярках меряцца ))))


Название: Re: Регулярное выражение с QString
Отправлено: Old от Июль 27, 2013, 12:55
Берем "среднестатистический" текст. Какая разница для интерактивного режима 0.03сек или 0.02???. Какая разница (например для моего компа) - затратит он 700к памяти или полтора мега, если у меня 8Гб на борту? Остается смотреть на скорость и понятность кодинга. Не? :-P
У каждого свой подход к оптимальности кода, я иногда месяцами пытаюсь выжать несколько процентов производительности.
А вообще, еще дельфи подтвердила, что все это глупости и для большинства современных программ, можно вообще ничего не оптимизировать и не о чем беспокоиться. Ну вылетит программ, ну запустит ее секретарша еще раз. Палец у нее не отвалиться. :)


Название: Re: Регулярное выражение с QString
Отправлено: Igors от Июль 27, 2013, 13:01
В целом смысл ясен. Но вот опять же опыта маловато, что бы с легкостью это делать. Конечно в идеале раз увидеть как это последовательно делается. Либо более долгий путь ковырять исходники примеров и постепенно выстраивать свою структуру. Пока протаптываем дорожки и бегаем по проторенным. Как нибудь и эту протопчим :).
Протопчем :) Последовательность простая

- создаете новые файлы cpp и h
- рисуете h файл, напр

Код
C++ (Qt)
#ifndef DAТABLOCK_H
#define DAТABLOCK_H
 
#include <QString>
struct CDataBlock {
 CDataBlock( void ) {};
 void Init( const QString & src );
 
//... члены данных как обсуждали выше
};
 
#endif  // DAТABLOCK_H
 
Дальше переносите все что можно из MainWindow в DataBlock.cpp. В результате "очищенный" метод выглядит примерно так
Код
C++ (Qt)
void MainWindow::bufferButtonSave()
{
   QClipboard *clipboard = QApplication::clipboard();
   mDataBlock.Init(clipboard->text());
   textory.clear();
   textory.enableAdd( true );
 
    QMapIterator<QString, int> it(mDataBlock.mFreqMap);
    while(it.hasNext())  {
       it.next();
       textory.addItem(Textory::Item(1, it.key() + "\t" + QString::number(it.value()));
    }
 
    QString total = QString::number(mDataBlock.mWords.size());
    ui.textoryWidget->getTextoryLabel().setText("Frequency list (" + total + ")" );
}
Это далеко от совершенства - никаких "выдач" пока нет, да и не очень хорошо лезть напрямую в члены класса (mDataBlock. ). Тем не менее схлопывание MainWindow налицо - анализатор занимается своим делом, UI - своим


Название: Re: Регулярное выражение с QString
Отправлено: Majestio от Июль 27, 2013, 13:16
У каждого свой подход к оптимальности кода, я иногда месяцами пытаюсь выжать несколько процентов производительности.
А вообще, еще дельфи подтвердила, что все это глупости и для большинства современных программ, можно вообще ничего не оптимизировать и не о чем беспокоиться. Ну вылетит программ, ну запустит ее секретарша еще раз. Палец у нее не отвалиться. :)
В принципе - согласен. За исключением ошибок. Программа вылетать не должна. Под оптимальностью я понимаю соразмерность усилий и величину выигрыша (или минимизацию проигрыша). Ну а в своей практике пытаюсь следовать двум "китам" стратегии:

1) Закон (принцип) Паретто (http://ru.wikipedia.org/wiki/%D0%97%D0%B0%D0%BA%D0%BE%D0%BD_%D0%9F%D0%B0%D1%80%D0%B5%D1%82%D0%BE)
2) Бритва Оккама (http://ru.wikipedia.org/wiki/%D0%91%D1%80%D0%B8%D1%82%D0%B2%D0%B0_%D0%9E%D0%BA%D0%BA%D0%B0%D0%BC%D0%B0)

Всегда помогают. Рекомендую :)


Название: Re: Регулярное выражение с QString
Отправлено: Igors от Июль 27, 2013, 13:51
Ну а в своей практике пытаюсь следовать двум "китам" стратегии:
В данном случае Вы не очень-то им следуете - впрочем как и остальные. Увлеклись частной задачей - как быстрейшим образом получить частоты (ассоциативный контейнер). Мне кажется здесь это не очень важно - годится любой приличный вариант. Важнее как гибко и удобно построить данные для разнообразных выдач. Напрашивается напр так
Код
C++ (Qt)
struct CData {
...
private:
QString mSource;
QVector <QStringRef> mWord;  // принципиально - храним слова
QHash <QStringRef, int> mFrequency;  // возможно строить по запросу
};
В свете этого придется заменить бздошный split на что-то свое - ну это норм. Однако все это ускользнуло от внимания оптимизаторов  :)


Название: Re: Регулярное выражение с QString
Отправлено: Majestio от Июль 27, 2013, 14:40
В данном случае Вы не очень-то им следуете - впрочем как и остальные. Увлеклись частной задачей - как быстрейшим образом получить частоты (ассоциативный контейнер).
Отнюдь. Затратив в 2 раза меньше времени на кодинг - получил результат на 3% хуже более скоростного. Профит на лицо. Принцип Паретто выполнен и перевыполнен. Более того, в других задачах (с нелинейными алгоритмами) мне придется исправить строчку-другую. Вам - сами подумайте)).


Название: Re: Регулярное выражение с QString
Отправлено: Majestio от Июль 27, 2013, 14:42
Напрашивается напр так
Не напрашивается пока. Не плодите сущности без необходимости. Просили частоты - отдали хэш. Это все.


Название: Re: Регулярное выражение с QString
Отправлено: Old от Июль 27, 2013, 15:05
Отнюдь. Затратив в 2 раза меньше времени на кодинг - получил результат на 3% хуже более скоростного. Профит на лицо. Принцип Паретто выполнен и перевыполнен.
Вот в этом и беда современной IT-индустрии. Поэтому и программы в своей массе все тормозят и требуют кучу ядер и памяти. В одной программе в одном месте на 10% просели, в другом на 15, в третьем 5. Вроде по отдельности мелочи, а программа работает на треть медленней. Ну это же фигня, пусть пользователь купит себе машину по быстрей.

Главный принцип в программировании это здравый смысл.


Название: Re: Регулярное выражение с QString
Отправлено: Igors от Июль 27, 2013, 17:47
Не напрашивается пока. Не плодите сущности без необходимости. Просили частоты - отдали хэш. Это все.
Какие же новые сущности я наплодил? :) Не лучше ли вместо копий слов держать ссылки на них? Вот Вам и оптимизация: по памяти вдвое, по скорости тоже будет прилично. Это "не мелочь по карманам тырить". А главное - мы всегда знаем место слова в исходном тексте, ценная возможность. Кстати в дусте идея та же - их итератор очень похож на QStringRef (ну или наоборот).


Название: Re: Регулярное выражение с QString
Отправлено: Majestio от Июль 27, 2013, 18:03
Какие же новые сущности я наплодил? :)
struct CData


Название: Re: Регулярное выражение с QString
Отправлено: Majestio от Июль 27, 2013, 18:08
Вот в этом и беда современной IT-индустрии. Поэтому и программы в своей массе все тормозят и требуют кучу ядер и памяти.
Тут другая беда, имхо. Быдлокодинг. Когда кодируют вообще без понимания применения и перспектив. Типа сдал - забыл. Повторюсь, каждому применению своя реализация. В рассматриваемом случае - если речь идет о обработке 700к-байтных текстов, моя реализация лучшая, в общем зачете. Если хотим сделать средство потоковой обработки - регэкспы нафик, возможно и С++ нафик.


Название: Re: Регулярное выражение с QString
Отправлено: Dancing_on_water от Июль 27, 2013, 18:10
Участвующим в замесе. Если хотите использовать регулярки, то лучше юзайте QRegularExpression


Название: Re: Регулярное выражение с QString
Отправлено: Old от Июль 27, 2013, 18:37
Тут другая беда, имхо.
Нет беда как раз в этом. И все ваши высказывания это подтверждают. :)

В рассматриваемом случае - если речь идет о обработке 700к-байтных текстов, моя реализация лучшая, в общем зачете.
Смешно. Чем она лучше? :)
Если она сливается как по скорости, так и по памяти.

Если хотим сделать средство потоковой обработки - регэкспы нафик, возможно и С++ нафик.
Вы же недавно мне расписывали достоинства регулярки для подобных задач. :)
И с++ нафик? А чем заменим? ;)


Название: Re: Регулярное выражение с QString
Отправлено: Majestio от Июль 27, 2013, 18:53
По скорости сливается на 3%. По количеству кодинга - меньше в 2 раза. Алаверды в квадрате)
Про регулярки я и не спорю - отличный бытовой инструмент. Но если хотите скорость в определенной выделенной задаче - решайте ее без фреймворков. Как-то так.


Название: Re: Регулярное выражение с QString
Отправлено: Igors от Июль 27, 2013, 19:44
По скорости сливается на 3%. По количеству кодинга - меньше в 2 раза. Алаверды в квадрате)
Посмотрим на "отдельно взятую" ф-цию split(). По сравнению с любой др реализацией кол-во кодинга может и меньше в 5 - или даже в 10 раз :) Но тот split Вам так или иначе придется заменить - и до 2 раз будет ой далеко  :)


Название: Re: Регулярное выражение с QString
Отправлено: Spark от Июль 27, 2013, 19:56
Igors Спасибо за развернутый пример. думаю воспользуюсь, когда окончательный вариант функции будет готов.

Сделал сортировку по убыванию частотности. Ну как смог, работает :). Покритикуйте, предлагайте свои варианты если не затруднит:
Код
C++ (Qt)
void MainWindow::bufferButtonSave()
{
   QClipboard *clipboard = QApplication::clipboard();
   QString originalText = clipboard->text();
   QString countItemFullString;
   QString countItemString;
   QStringList itemList;
   int countItem(0);
   int countItemFull(0);
 
   originalText = originalText.toLower();
   originalText.replace(QRegExp("\\W"), " ");
   originalText.replace(QRegExp("\\d"), " ");
   originalText.replace(QRegExp("_"), " ");
   // ЗАДАЧА1: ЭТО НЕ РАБОТАЕТ
   originalText.replace(QRegExp("[а-я]"), "");
 
   textory.clear();
 
   itemList = originalText.split(QRegExp("\\s+"),QString::SkipEmptyParts);
   QMap <QString, int> frequencyMap;
   foreach (QString Item, itemList) ++frequencyMap[Item];
 
   QList<QString> frequencyList;
   QMapIterator<QString,int> Iter(frequencyMap);
   while(Iter.hasNext())
   {
       Iter.next();
       countItem = Iter.value();
       countItemString.setNum(countItem);
       if(countItem <10 )countItemString = "0000" + countItemString;
       if(countItem >9 && countItem <100 )countItemString = "000" + countItemString;
       if(countItem >99 && countItem <1000 )countItemString = "00" + countItemString;
       if(countItem >999 && countItem <10000 )countItemString = "0" + countItemString;
       countItemFull = countItemFull + countItem;
       frequencyList.append(countItemString + "_" + Iter.key() );
   }
 
   qSort(frequencyList);
 
   textory.enableAdd( true );
 
   QString wordItem, wordCount;
 
   foreach (QString itm, frequencyList)
   {
       wordItem = itm;
       wordCount = itm;
       wordItem.remove(0,6);
       wordCount.remove(5,100);
       wordCount.remove(QRegExp("^[0]"));
       wordCount.remove(QRegExp("^[0]"));
       wordCount.remove(QRegExp("^[0]"));
       wordCount.remove(QRegExp("^[0]"));
       textory.addItem( Textory::Item( 1, wordItem + "\t" + wordCount ) );
   }
 
   countItemFullString.setNum(countItemFull);
 
   ui.textoryPaneWidget->getTextoryLabel().setText( "Frequency list (" + countItemFullString + ")" );
}
Что не нравится, так это то, что в обратном алфавитном порядке. Однако, сравнив с программой образцом, там та же ситуация. Хотелось бы улучшить.
Ну и вопрос №1 остается - оставить нужный язык.


Название: Re: Регулярное выражение с QString
Отправлено: Dancing_on_water от Июль 27, 2013, 20:03
To Spark а с каким объемом текста имеет делу функция и как часто?


Название: Re: Регулярное выражение с QString
Отправлено: Spark от Июль 27, 2013, 20:24
Обычный объем, для тех нужд для которых предполагается - тысячи 2-3 не больше. Но вполне реальны тексты на 2-3 сотни тысяч слов. Сложно предсказать кто для чего ее захочет использовать. На самом деле предполагается довольно крутую обработку текста делать.


Название: Re: Регулярное выражение с QString
Отправлено: Old от Июль 27, 2013, 20:37
Обычный объем, для тех нужд для которых предполагается - тысячи 2-3 не больше. Но вполне реальны тексты на 2-3 сотни тысяч слов. Сложно предсказать кто для чего ее захочет использовать. На самом деле предполагается довольно крутую обработку текста делать.
Для крутой обработки текста нужны алгоритмы, которые эту о работку будут делать. Сейчас нужно обдумывать базу этих алгоритмов, что может понадобиться и в каком виде. Другими словами заняться проектированием, а вы какую-то ерунду сейчас делаете, да еще и с Gui. Когда дойдет время до крутой обработки, все что вы сделаете сейчас придется выкинуть.


Название: Re: Регулярное выражение с QString
Отправлено: Dancing_on_water от Июль 27, 2013, 20:45
Ну тогда у вас в корне неверный подход 2-3 тысяч слов это объем около 20-40 кБ.  Уже много. И хотя и сильно больший объем влезет в кэш, НО

Вам надо экономить на всем и не в последнюю очередь на обращение к памяти. У вас уже здесь 5 полных прохода

Код
C++ (Qt)
originalText = originalText.toLower();
   originalText.replace(QRegExp("\\W"), " ");
   originalText.replace(QRegExp("\\d"), " ");
   originalText.replace(QRegExp("_"), " ");
   originalText.replace(QRegExp("[а-я]"), "");
 
А вот это
Код
C++ (Qt)
 
   itemList = originalText.split(QRegExp("\\s+"),QString::SkipEmptyParts);
Вообще затормозит систему так, что мама не горюй

Не говоря уже о том, что регулярные выражения для этого дела - крайне медленный и плохой инструмент.


Название: Re: Регулярное выражение с QString
Отправлено: Spark от Июль 27, 2013, 20:58
Dancing_on_water
Согласен, что надо экономить. Однако я не в курсе как :). Слишком мал опыта. По сути каждое новое действие это единственный приобретенный опыт и сравнивать не с чем.
Но по поводу нынешнего кода. На моей системе, стандартные задачи 2 - 3 тысячи даже не стоит и беспокоится. Моментально. Текст на 40000 небольшая задержка. Пользователь не заметит и не будет раздражен.
Сделал эксперимент и подсунул текст на 5812357 слов из буфера обмена. Наибольшая частот слова в этом тексте 82110.
Забыл отметить конец теста. Ну где то 10-15 минут. Но это исключительный текст, ради эксперимента.


Название: Re: Регулярное выражение с QString
Отправлено: Spark от Июль 27, 2013, 21:02
И все так по существу вопроса. Фактически надо решить последнюю задачу.
Как сделать, что бы отрабатывался такой регесп:
Код
C++ (Qt)
   originalText.replace(QRegExp("[а-я]"), "");
С английским, естественно, нет проблем и это работает:
Код
C++ (Qt)
   originalText.replace(QRegExp("[a-z]"), "");


Название: Re: Регулярное выражение с QString
Отправлено: Spark от Июль 27, 2013, 21:04
Dancing_on_water
Согласен, что надо экономить. Однако я не в курсе как :). Слишком мал опыта. По сути каждое новое действие это единственный приобретенный опыт и сравнивать не с чем.
Но по поводу нынешнего кода. На моей системе, стандартные задачи 2 - 3 тысячи даже не стоит и беспокоится. Моментально. Текст на 40000 небольшая задержка. Пользователь не заметит и не будет раздражен.
Сделал эксперимент и подсунул текст на 5812357 слов из буфера обмена. Наибольшая частот слова в этом тексте 82110.
Забыл отметить конец теста. Ну где то 10-15 минут. Но это исключительный текст, ради эксперимента.

P.S. Я подумаю, чем заменить регулярки.


Название: Re: Регулярное выражение с QString
Отправлено: m_ax от Июль 27, 2013, 21:11
P.S. Я подумаю, чем заменить регулярки.

Вам сейчас не об этом надо думать, а вот о чём:

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


Название: Re: Регулярное выражение с QString
Отправлено: Spark от Июль 27, 2013, 21:17
И все таки несмотря ни на, что я знаю над чем именно сейчас мне думать. Лучше ближе к делу, к конкретно поставленному вопросу. Сейчас я работаю над вполне стандартным функционалом для программ данной категории.

Поточнее засек время. почти 6 миллионов слов обработала за 10 минут.


Название: Re: Регулярное выражение с QString
Отправлено: m_ax от Июль 27, 2013, 22:04
И все таки несмотря ни на, что я знаю над чем именно сейчас мне думать. Лучше ближе к делу, к конкретно поставленному вопросу. Сейчас я работаю над вполне стандартным функционалом для программ данной категории.

Поточнее засек время. почти 6 миллионов слов обработала за 10 минут.

Вот в том то и оно..
К вашему сведению, в файле test.txt, что прилагался к тестам (см. посты выше) более шести миллионов слов  и обработка там занимала (с учётом 100 кратного повторения) - секунды, т.е., фактически, по времени у вас на три порядка (в 1000 раз!) медленнее..      
Делайте выводы..


Название: Re: Регулярное выражение с QString
Отправлено: Old от Июль 27, 2013, 22:26
Какие же новые сущности я наплодил? :) Не лучше ли вместо копий слов держать ссылки на них? Вот Вам и оптимизация: по памяти вдвое, по скорости тоже будет прилично. Это "не мелочь по карманам тырить". А главное - мы всегда знаем место слова в исходном тексте, ценная возможность. Кстати в дусте идея та же - их итератор очень похож на QStringRef (ну или наоборот).

Поясните пожалуйста, на какие строки будут держаться ссылки в хеше?
Код
C++ (Qt)
struct CData {
...
QHash <QStringRef, int> mFrequency;  // возможно строить по запросу
};
 

Вот есть текст:
aaa bbb ccc aaa ddd aaa

На какую из этих строк "aaa" будет ссылка в хеше?


Название: Re: Регулярное выражение с QString
Отправлено: kambala от Июль 27, 2013, 22:46
И все так по существу вопроса. Фактически надо решить последнюю задачу.
Как сделать, что бы отрабатывался такой регесп:
Код
C++ (Qt)
   originalText.replace(QRegExp("[а-я]"), "");
С английским, естественно, нет проблем и это работает:
Код
C++ (Qt)
   originalText.replace(QRegExp("[a-z]"), "");
проблема в несоответствии кодировки исходников и обрабатываемого текста. чтобы этого избежать, задавай в коде русские буквы (да и вообще все не-ASCII символы) их unicode-кодом.


Название: Re: Регулярное выражение с QString
Отправлено: Igors от Июль 28, 2013, 03:59
На какую из этих строк "aaa" будет ссылка в хеше?
Ну "не мудрствуя лукаво" - на первую. Хотя тут есть гораздо более интересные ходы. Напр вообще без ассоциативного контейнера
Код
C++ (Qt)
struct CTextAnalyzer {  // имя посочнее
...
private:
 QString mSource;
 QVector <QStringRef> mWord;   // слова по порядку
 QVector <QStringRef> mFreqWord; // слова по частоте
 QVector <int> mFreqEntry;  // индекс слова в mFreqWord
};
И наверное QStringRef избыточен, лучше просто typedef QPair <int, int> ...


Название: Re: Регулярное выражение с QString
Отправлено: Igors от Июль 28, 2013, 04:04
И все таки несмотря ни на, что я знаю над чем именно сейчас мне думать.
Пока Вы будете лепить все в MainWindow - это "мартышкин труд", ну никак не более того.


Название: Re: Регулярное выражение с QString
Отправлено: Old от Июль 28, 2013, 06:41
Хотя тут есть гораздо более интересные ходы.
Вначале нужно разобраться, какая крутая обработка текста вообще планируется, хотя бы основные направления.


Название: Re: Регулярное выражение с QString
Отправлено: Spark от Июль 28, 2013, 15:08
Основные вопросы решены (сортировка по частоте, оставить английский). Настало время оптимизации и выбора более лучшего алгоритма. Критикуйте:
Код
C++ (Qt)
void MainWindow::bufferButtonSave()
{
   QClipboard *clipboard = QApplication::clipboard();
   QString originalText = clipboard->text();
   QString countItemFullString;
   QString countItemString;
   QStringList itemList;
   int countItem(0);
   int countItemFull(0);
 
   originalText = originalText.toLower();
   originalText.replace(QRegExp("\\W"), " ");
   originalText.replace(QRegExp("\\d"), " ");
   originalText.replace(QRegExp("_"), " ");
   // УБИРАЕМ РУССКИЙ
   originalText.replace(QRegExp(QString::fromUtf8("[а-яё]")), "");
 
   textory.clear();
 
   itemList = originalText.split(QRegExp("\\s+"),QString::SkipEmptyParts);
   QMap <QString, int> frequencyMap;
   foreach (QString Item, itemList) ++frequencyMap[Item];
 
   QList<QString> frequencyList;
   QMapIterator<QString,int> Iter(frequencyMap);
   while(Iter.hasNext())
   {
       Iter.next();
       countItem = Iter.value();
       countItemString.setNum(countItem);
       // ОРГАНИЗОВЫВАЕМ СОРТИРОВКУ
       if(countItem <10 )countItemString = "0000" + countItemString;
       if(countItem >9 && countItem <100 )countItemString = "000" + countItemString;
       if(countItem >99 && countItem <1000 )countItemString = "00" + countItemString;
       if(countItem >999 && countItem <10000 )countItemString = "0" + countItemString;
       countItemFull = countItemFull + countItem;
       frequencyList.append(countItemString + "_" + Iter.key() );
   }
 
   qSort(frequencyList);
 
   textory.enableAdd( true );
 
   QString wordItem, wordCount;
 
   foreach (QString itm, frequencyList)
   {
       wordItem = itm;
       wordCount = itm;
       wordItem.remove(0,6);
       wordCount.remove(5,100);
       wordCount.remove(QRegExp("^[0]"));
       wordCount.remove(QRegExp("^[0]"));
       wordCount.remove(QRegExp("^[0]"));
       wordCount.remove(QRegExp("^[0]"));
       textory.addItem( Textory::Item( 1, wordItem + "\t" + wordCount ) );
   }
 
   countItemFullString.setNum(countItemFull);
 
   ui.textoryPaneWidget->getTextoryLabel().setText( "Frequency list (" + countItemFullString + ")" );
}
Есть небольшой косячок. Если взять смешанный текст из текстового редактора то все Ok! Но например, если из самого QT взять смешанный текст и отправить на обработку, то то-же все Ok! Но если для сравнения сначала отправляю в подобную эталонную программку, а затем этот же текст на свою обработку, то уже русские не удаляются и притом в крягозябрах. Может это и не страшно, но хотелось бы исключить такой подвох.



И все таки несмотря ни на, что я знаю над чем именно сейчас мне думать. Лучше ближе к делу, к конкретно поставленному вопросу. Сейчас я работаю над вполне стандартным функционалом для программ данной категории.

Поточнее засек время. почти 6 миллионов слов обработала за 10 минут.

Вот в том то и оно..
К вашему сведению, в файле test.txt, что прилагался к тестам (см. посты выше) более шести миллионов слов  и обработка там занимала (с учётом 100 кратного повторения) - секунды, т.е., фактически, по времени у вас на три порядка (в 1000 раз!) медленнее..      
Делайте выводы..
Я не писал, что мой код оптимален. Ткните пальцем какой из предложенных алгоритмов выбрать и почему, попробую воспроизвести в реальных условиях (не в тестовых), со всей последующей обработкой, вот тогда смогу оценить по достоинству.
А пока же могу сказать, что моя функция работает лучше, чем та которую брал за эталон. Правда там тоже видно начинающий делал, но в своем роде аналогов то больше и нет особо.


Название: Re: Регулярное выражение с QString
Отправлено: Spark от Июль 28, 2013, 17:31
Второй способ убрать Русский.
Код
C++ (Qt)
   // УБИРАЕМ ВСЕ КРОМЕ АНГЛИЙСКОГО
   originalText.replace(QRegExp(QString::fromUtf8("[a-z]")), " ");
Вроде как полностью решает проблему с кодировкой. И вообще получается в один проход можно сразу разделить весь текст.


Название: Re: Регулярное выражение с QString
Отправлено: Spark от Июль 28, 2013, 19:27
Не поленился проверил свою реализацию и реализацию эталон (чужую программку), которую юзал раньше:
Всего слов:
4352212 - всего слов насчитала моя реализация
4352217 - всего слов насчитал эталон
15 минут - вычисляла моя реализация
70 минут - вычислял эталон

Однако, эталон без сортировки ставит слова в порядке поступления, что есть хорошо. То же делал мой первый вариант (скорость не проверял, но видимо алгоритм схож).
Моя программа сортирует (мапа сортирует сразу) и это плохо. Если не удастся нормально реализовать этот режим, то придется как то совмещать два подхода.


Название: Re: Регулярное выражение с QString
Отправлено: kambala от Июль 28, 2013, 19:56
QHash не сортирует


Название: Re: Регулярное выражение с QString
Отправлено: Old от Июль 28, 2013, 20:17
Не поленился проверил свою реализацию и реализацию эталон (чужую программку), которую юзал раньше:
Всего слов:
4352212 - всего слов насчитала моя реализация
4352217 - всего слов насчитал эталон
15 минут - вычисляла моя реализация
70 минут - вычислял эталон
Вот об этом m_ax и говорит, это ужасный результат.
В наших тестах 6107300 слов обрабатываются за чуть более 5 секунд (на моей машине).


Название: Re: Регулярное выражение с QString
Отправлено: Spark от Июль 28, 2013, 20:20
Не поленился проверил свою реализацию и реализацию эталон (чужую программку), которую юзал раньше:
Всего слов:
4352212 - всего слов насчитала моя реализация
4352217 - всего слов насчитал эталон
15 минут - вычисляла моя реализация
70 минут - вычислял эталон
Вот об этом m_ax и говорит, это ужасный результат.
В наших тестах 6107300 слов обрабатываются за чуть более 5 секунд (на моей машине).

Я полагаю наши тексты отличаются. Но сейчас буду экспериментировать и смотреть различия между вашими реализациями и моей.


Название: Re: Регулярное выражение с QString
Отправлено: Spark от Июль 28, 2013, 20:23
QHash не сортирует
Спасибо. Это хорошая новость.

Расставил таймеры. Проверил где наибольшие тормоза:
Код
C++ (Qt)
   originalText = originalText.toLower();
 
   qDebug() << tm.elapsed();
 
   tm.start();
 
   // УБИРАЕМ РУССКИЙ
   originalText.replace(QRegExp("[^a-z]"), " ");
   originalText.replace(QRegExp("_"), " ");
 
   qDebug() << tm.elapsed();
 
   tm.start();
 
   textory.clear();
 
   itemList = originalText.split(QRegExp("\\s+"),QString::SkipEmptyParts);
   QMap <QString, int> frequencyMap;
   foreach (QString Item, itemList) ++frequencyMap[Item];
 
   qDebug() << tm.elapsed();
 
   tm.start();
 
   QList<QString> frequencyList;
   QMapIterator<QString,int> Iter(frequencyMap);
   while(Iter.hasNext())
   {
       Iter.next();
       countItem = Iter.value();
       countItemString.setNum(countItem);
       // ОРГАНИЗОВЫВАЕМ СОРТИРОВКУ
       if(countItem <10 )countItemString = "0000" + countItemString;
       if(countItem >9 && countItem <100 )countItemString = "000" + countItemString;
       if(countItem >99 && countItem <1000 )countItemString = "00" + countItemString;
       if(countItem >999 && countItem <10000 )countItemString = "0" + countItemString;
       countItemFull = countItemFull + countItem;
       frequencyList.append(countItemString + "_" + Iter.key() );
   }
 
   qDebug() << tm.elapsed();
 
   tm.start();
 
   qSort(frequencyList);
 
   textory.enableAdd( true );
 
   QString wordItem, wordCount;
 
   qDebug() << tm.elapsed();
 
   tm.start();
 
   foreach (QString itm, frequencyList)
   {
       wordItem = itm;
       wordCount = itm;
       wordItem.remove(0,6);
       wordCount.remove(5,100);
       wordCount.remove(QRegExp("^[0]"));
       wordCount.remove(QRegExp("^[0]"));
       wordCount.remove(QRegExp("^[0]"));
       wordCount.remove(QRegExp("^[0]"));
       textory.addItem( Textory::Item( 1, wordItem + "\t" + wordCount ) );
   }
 
   qDebug() << tm.elapsed();
Результаты:
316
919942
12435
542
110
103253
Картина ясная. Будем думать.


Название: Re: Регулярное выражение с QString
Отправлено: Spark от Июль 28, 2013, 20:55
Как то не так все просто получается.
Сократил время работы самой функции до 2х минут. Убрал все регеспы, оставил только сплит:
Код
C++ (Qt)
   itemList = originalText.split(QRegExp("[^a-z]"),QString::SkipEmptyParts);
При этом вывод результатов на экран все все таки задерживается еще на 5 минут.
Итого 7 минут. Это лучше, и эти 5 минут уже не от меня зависят. Попробую пошаманить еще над своим кодом.


Название: Re: Регулярное выражение с QString
Отправлено: Spark от Июль 28, 2013, 21:26
К слову сказать, та часть функции которую вы замеряете у меня выполняется за 20 секунд. Однако вряд ли условия тестов одинаковы. От самого текста полагаю многое зависит и кроме того мой регесп удаляет весь мусор.


Название: Re: Регулярное выражение с QString
Отправлено: Spark от Июль 28, 2013, 21:45
Полагаю здесь грубовато сделал:
Код
C++ (Qt)
       wordCount.remove(5,100);
       wordCount.remove(QRegExp("^[0]"));
       wordCount.remove(QRegExp("^[0]"));
       wordCount.remove(QRegExp("^[0]"));
       wordCount.remove(QRegExp("^[0]"));
Текст специфически и на выходе много слов. Потери в этом месте до 1,5 минут на моем тесте. В реальных текстах, вряд ли такое будет. Но все таки лучше сделать правильно.  Как оптимально удалить начальные нули в строковой переменной? Думаю можно было обойтись вообще без регеспа.


Название: Re: Регулярное выражение с QString
Отправлено: m_ax от Июль 29, 2013, 00:23
Полагаю здесь грубовато сделал:
Код
C++ (Qt)
       wordCount.remove(5,100);
       wordCount.remove(QRegExp("^[0]"));
       wordCount.remove(QRegExp("^[0]"));
       wordCount.remove(QRegExp("^[0]"));
       wordCount.remove(QRegExp("^[0]"));
Текст специфически и на выходе много слов. Потери в этом месте до 1,5 минут на моем тесте. В реальных текстах, вряд ли такое будет. Но все таки лучше сделать правильно.  Как оптимально удалить начальные нули в строковой переменной? Думаю можно было обойтись вообще без регеспа.

Возвёл очи к небу..


Название: Re: Регулярное выражение с QString
Отправлено: Majestio от Июль 29, 2013, 09:38
Spark, попробую еще раз на пальцах обсудить вашу задачу и ваше стремление научится программированию...

Общие вопросы

1) Заходя на форум с вопросами, научитесь слушать и заставьте себя слышать. Это не просто, но, в конечном счете, сэкономит вам кучу времени. Участники не пытаются вас "выставить дураком", напротив тратят свое время вам на помощь. Все когда-то начинали. Учится на своих ошибках - хорошо, но еще лучше - на ошибках других. А каждый совет участников - результат некогда экспериментов и в конечном счете потраченного времени. У вас его больше чем у других?
2) Поймите, что умение кодировать и умение программировать - это разные понятия. Вы их до сих пор путаете. Кодирование - это умение представить алгоритм на выбранном языке программирования (или без, крайне редкий случай) с учетом его синтаксиса. Программирование - это умение кодировать предварительно разработанные и оптимизированные алгоритмы с учетом постановки задачи. Пишу от себя, стараясь выхватить суть. Конечно еще есть нюансы (проектирование архитектуры, выбор средств и пр... опускаю).
3) Вам настоятельно советуют: четкое определение постановки задачи, отделение кода обработки от средств UI. Вы этому не предаете значение, это печально. Попробую написать аналогию, чтобы вы посмотрели на свои действия "нашими" глазами:

Парни, я не строитель, но у меня есть две доски, шурупы, отвертка и молоток. Надо соединить две доски. Я не умею, поэтому пока просто пытаюсь научится забивать шурупы. Беру шуруп, ставлю под угдом 45 градусов и забиваю его. Покритикуйте! Вам отвечают - нужно использовать другие методы соединения. То что вы делаете - не правильно, хотя и возможно. Вы закрываете уши и пытаетесь вбить шуруп под углом 90 градусов. Шуруп входит легче - у вас поднимается настроение ...

Но есть более правильный способ - шуруп ввинчивать отверткой! См п.1.

Частные вопросы

4) Постановка задачи? Ее так и нет ... Вы говорите  - один текст считается быстро, другой непонятно как.  Это должно быть в постановке задачи, к примеру важно определиться с кодировкой. Если кодировка с фиксированной длиной символа (к примеру win-1251) - ему свой алгоритм, если с переменной (к примеру, UTF-8) - ему свой. Конечно второй алгоритм сможет обрабатывать и первый вариант, но накладных расходов будет ну очень много. В случае вашей озвученной задачи, для текста с кодировкой с фиксированной длиной символа - регэкспы возможно вовсе выкинуть. Регэкспы - это средство поиска языковых конструкций, символы-разделители - ими являются, но их можно обрабатывать и быстрее (подход Old хорош, а для 8-битного текста можно еще на порядок ускорить, почти уверен). В нашем случае (захотели обрабатывать UTF-8) - это понятный и простой способ выделения слов в тексе с кодировкой с переменной  длиной символа.

5) Отделите "мухи от котлет". Рассово-правильно :) выносить обработчики из основного кода UI - либо в виде классов (подход ООП), либо в виде библиотеки процедур (классический процедурно-ориентированный подход).

6) В плане обработки текста есть три основных подхода:

а) поиск целевого содержимого
б) чистка "мусора"
в) комбинация первых двух

Вы должны для себя определиться - чем занимаетесь вы в своем коде. Что в вашем случае предпочтительнее. Посмотрите на подход Igors - он поскромничал или решил не выдавать военную тайну)) Он предлагает класс-индексатор. Хотя не совсем правильно, имхо, с точки зрения реализации. Нужно выделять индексы слов в тексте без учета их содержимого (ибо повторяются), а если бы не повторялись - 2-ая трата памяти все равно. Индексация решает вопрос экономии памяти и скорости доступа. В качестве индекса должна использоваться пара (смещение начала слова в тексте,его длина). Если вам не дай боже придется анализировать 10-20 Гигабайтные тексты - то предлагаемые тут способы не прокатят ни разу. Нужно будет кусками читать текст в память (строить индекс, если потребуется дальнейшее обращение к словам), и обрабатывать по ходу сканирования (см. алгоритм Old, его принцип).

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


Название: Re: Регулярное выражение с QString
Отправлено: Spark от Июль 29, 2013, 09:47
Ok! Переделал сортировку по частотности (заодно обнаружил, что нулей не хватало :)). Критикуйте:
Код
C++ (Qt)
void MainWindow::bufferButtonSave()
{
   QTime tm;
 
   tm.start();
 
   QClipboard *clipboard = QApplication::clipboard();
   QString originalText = clipboard->text();
   QString countItemFullString;
   QString countItemString, countItemStringZero;
   QStringList itemList;
   int countItem(0);
   int countItemFull(0);
 
   qDebug() << "Reade Data: " << tm.elapsed();
 
   tm.start();
 
   originalText = originalText.toLower();
 
   qDebug() << "Data toLower: " << tm.elapsed();
 
   textory.clear();
 
   tm.start();
 
   itemList = originalText.split(QRegExp("[^a-z]"),QString::SkipEmptyParts);
   QHash<QString, int> frequencyMap;
   foreach (QString Item, itemList) ++frequencyMap[Item];
 
   qDebug() << "Data split [^a-z]: " << tm.elapsed();
 
   tm.start();
 
   QList<QString> frequencyList;
   QHashIterator<QString,int> Iter(frequencyMap);
   while(Iter.hasNext())
   {
       Iter.next();
       countItem = Iter.value();
       countItemString.setNum(countItem);
       countItemStringZero = countItemString;
       // ОРГАНИЗОВЫВАЕМ СОРТИРОВКУ
       if(countItem <10 )countItemStringZero = "00000" + countItemStringZero;
       if(countItem >9 && countItem <100 )countItemStringZero = "0000" + countItemStringZero;
       if(countItem >99 && countItem <1000 )countItemStringZero = "000" + countItemStringZero;
       if(countItem >999 && countItem <10000 )countItemStringZero = "00" + countItemStringZero;
       if(countItem >9999 && countItem <100000 )countItemStringZero = "0" + countItemStringZero;
       countItemFull = countItemFull + countItem;
       frequencyList.append(countItemStringZero + "_" + Iter.key() + "\t" + countItemString );
   }
 
   qDebug() << "Add zero: " << tm.elapsed();
 
   tm.start();
 
   qSort(frequencyList);
 
   textory.enableAdd( true );
 
   QString wordItem, wordCount;
 
   qDebug() << "Data sort: " << tm.elapsed();
 
   tm.start();
 
   foreach (QString itm, frequencyList)
   {
       itm.remove(0,7);
       textory.addItem( Textory::Item( 1, itm ) );
   }
 
   qDebug() << "Clear zero: " << tm.elapsed();
 
   tm.start();
 
   countItemFullString.setNum(countItemFull);
 
   ui.textoryPaneWidget->getTextoryLabel().setText( "Frequency list (" + countItemFullString + ")" );
 
   qDebug() << "Write name: " << tm.elapsed();
}
Текст на входе  не из простых. Вот вывод результата:
(http://s018.radikal.ru/i506/1307/57/540514949fb6t.jpg) (http://radikal.ru/fp/d80f0d23fe1a4e438fdad5f0fd873298)
В скобках всего слов. Дальше оригинальных слов

Результат теста:
Reade Data:  8745
Data toLower:  310
Data split [^a-z]:  15249
Add zero:  757
Data sort:  93
Clear zero:  413837
Write name:  1

Против старого:
Reade Data:  8837
Data toLower:  308
Data split [^a-z]:  16566
Add zero:  544
Data sort:  89
Clear zero:  406562
Write name:  0

Как видим в общем то ничего не изменилось.
Закоментировал вывод:
Код
C++ (Qt)
       textory.addItem( Textory::Item( 1, itm ) );
Результат теста новой реализации:
Reloading all the tabs...
Reade Data:  9584
Data toLower:  323
Data split [^a-z]:  16117
Add zero:  772
Data sort:  91
Clear zero:  94

Результат старой реализации:
Reloading all the tabs...
Reade Data:  8949
Data toLower:  310
Data split [^a-z]:  16196
Add zero:  541
Data sort:  93
Clear zero:  759
Write name:  0


Да на порядок хуже :). Но абсолютно не важно. И тот и другой вариант меньше секунды.


Название: Re: Регулярное выражение с QString
Отправлено: Majestio от Июль 29, 2013, 09:52
Ok! Переделал сортировку по частотности (заодно обнаружил, что нулей не хватало :)). Критикуйте:
В Qt есть средства форматирования.
if(countItem <10 )countItemStringZero = "00000" + countItemStringZero;
if(countItem >9 && countItem <100 )countItemStringZero = "0000" + countItemStringZero;
if(countItem >99 && countItem <1000 )countItemStringZero = "000" + countItemStringZero;
if(countItem >999 && countItem <10000 )countItemStringZero = "00" + countItemStringZero;
if(countItem >9999 && countItem <100000 )countItemStringZero = "0" + countItemStringZero;
Решается одним оператором: QString QString::arg

Прочтите мой пост выше, пожалуйста :)


Название: Re: Регулярное выражение с QString
Отправлено: Spark от Июль 29, 2013, 09:56
По поводу очередных нравоучений. Я все понимаю и внемлю. Это раз!
Не без вашей помощи. Но помощь процентов на 80 заключается в постановке ответа - гомнокод, быдлокод (честно говоря у меня еле язык поворачивается, ну раз так принято...). Во всяком случае для меня это означает одно - можно лучше и я переделываю. Это двас!
Моя программа уже лучше работает чем аналоги профи, за плечами которых лет по пять (напомню у меня за плечами 2 месяца). Это трис!
Еще непонятки есть по этому вопросу?
Вы из меня хотите профи сделать за пару месяцев? В кокой то мере удается :). И я за это благодарен.


Название: Re: Регулярное выражение с QString
Отправлено: Spark от Июль 29, 2013, 09:58
Решается одним оператором: QString QString::arg
Такой ответ мне больше по душе. Пользы от него намного больше, чем от нравоучений.
Спасибо!

P.S. Вы же видите, что двигаюсь я попорядку. Бессмысленно в моем положении охватывать все сразу, кода я плохо знаю инструментарий. Сделал плохо, но сделал. Подсказали, что можно лучше, делаем лучше. И .т.д.


Название: Re: Регулярное выражение с QString
Отправлено: Majestio от Июль 29, 2013, 10:13
Вы из меня хотите профи сделать за пару месяцев?
Не в коей мере - это зависит только от вас.
Просто есть, и я уже описал, базовые принципы - игнорирование которых есть моветон (можно написать и быдлокод). Зачем вам начинать неправильно, если вам дают ГОТОВЫЕ РЕКОМЕНДАЦИИ?

Это даст:

понятность реализации
скорость выполнения
экономию накладных расходов
возможно удобное повторное использование кода

В чем суть вашего "игнора"? Если скажите что нравиться "ходить по граблям" - я пойму.
А так просто в непонятках.


Название: Re: Регулярное выражение с QString
Отправлено: Majestio от Июль 29, 2013, 10:18
P.S. Вы же видите, что двигаюсь я попорядку.

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

Это расточительно по времени - да и несколько неправильно с точки зрения форумного общения. Тут принято предлагать "как", а не анализировать в каком именно операторе или блоке кода вы накосячили.

Ладно, дело ваше. Только вы же должны понимать - если форумчанин вам ответит, вы решите что это не важно, начнете "доделывать" свое ... Второй раз отвечать желание пропадет, ибо впустую.


Название: Re: Регулярное выражение с QString
Отправлено: Igors от Июль 29, 2013, 11:03
Ok! Переделал сортировку по частотности (заодно обнаружил, что нулей не хватало :)). Критикуйте:
Уже критиковали. Как сделать сортировку нормально - код приводили. Хотите делать какую-то свою сортировку (через склейку строк) - на здоровье, но это никому не интересно, потому что просто хуже, длиннее и  медленнее. Зачем Вы уже третий раз навязываете это бесполезное обсуждение?

Сформулируйте задачу, выделите класс - тогда может поговорим. А будете упираться и приводить очередной MainWindow - на том же месте и останетесь.


Название: Re: Регулярное выражение с QString
Отправлено: Spark от Июль 29, 2013, 11:13
Как сделать сортировку нормально - код приводили.
В общем то мой код работает быстро. Но хотелось бы увидеть тот код который предлагали.  Ну а замеров тут столько наделано, что не удивительно, что я что то пропустил, тем более без пояснений, что это именно ответ на мой вопрос.


Название: Re: Регулярное выражение с QString
Отправлено: Spark от Июль 29, 2013, 11:14
P.S. Вы же видите, что двигаюсь я попорядку.

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

Это расточительно по времени - да и несколько неправильно с точки зрения форумного общения. Тут принято предлагать "как", а не анализировать в каком именно операторе или блоке кода вы накосячили.

Ладно, дело ваше. Только вы же должны понимать - если форумчанин вам ответит, вы решите что это не важно, начнете "доделывать" свое ... Второй раз отвечать желание пропадет, ибо впустую.
Однако, за основу я взял ваш вариант.
На остальные вопросы я не получил ответа и свои варианты предложил. Опять же не получил критических замечаний, ни иные способы решения поставленной задачи.
Все, что мимо поставленной задачи, я записываю.
Я пояснял, что взял исходники и добавляю свой функционал. Следовательно зажат рамками тех кто делал программу до меня. Приходится разбираться как она устроена изнутри.
И могу сказать, что на сегодня уже могу поправить то, что накосячили до меня программисты со стажем лет пять, а так же снять ограничения в связи с бывшей малой скоростью обработки. Мой код работает быстрее на порядок.

И все таки ближе к делу. Глядя на последний предложенный код, видно, что расчленение на слова происходит относительно долго. Можно ли ускорить процесс? Хочу двигаться в этом направлении. Как только код будет наиболее быстр, так сразу попробую отделить мух от борща. Но прежде хотелось бы узнать, а прирост в скорости это даст?


Название: Re: Регулярное выражение с QString
Отправлено: Majestio от Июль 29, 2013, 11:16
И результаты у меня такие (release)

Код
Bash
Old: 15629 15211
Majestio: 17590 15211
m_ax: [b]9028[/b]  15211
 
Хе, хе ;)

Ланна, простите за оффтопик  :P ...

Код
Perl
#!/usr/bin/perl
 
use Time::HiRes qw(gettimeofday);
 
open(FD,"test.txt") || die "Shit happiness!";
$T = join("",<FD>);
close(FD);
 
$Start = gettimeofday();
 
for($I=0; $I<100; $I++) {
 map { $F{$_}++ } split(/[\s\.,:;\-()]+/,$T);
}
 
$Elapsed = gettimeofday() - $Start;
 
print "<br>Elapsed: $Elapsed";
 

Результат: 3484 ;D (в ТЗ речи об UI не было ... к разговору об регэкспах ....)


Название: Re: Регулярное выражение с QString
Отправлено: Majestio от Июль 29, 2013, 11:24
И все таки ближе к делу. Глядя на последний предложенный код, видно, что расчленение на слова происходит относительно долго. Можно ли ускорить процесс?

1) Откажитесь от кодировок и сделайте для одной 8-битной с фиксированной длинной символа (к примеру, win-1251)
2) Откажитесь от регэкспов, работайте с символами (например через switсh)
3) Откажитесь от манипуляции с QString в качестве хранителя текста - используйте *char
4) Частоты заносите в QHash

По поводу п.3 - просто подозрение,  все равно будут преобразования для добавления в QHash, проверить бы ...


Название: Re: Регулярное выражение с QString
Отправлено: m_ax от Июль 29, 2013, 11:27
Результат: 3484 ;D (в ТЗ речи об UI не было ... к разговору об регэкспах ....)

И как это число соотносится с результатами, полученными на моём железе?  ???
 


Название: Re: Регулярное выражение с QString
Отправлено: m_ax от Июль 29, 2013, 11:33
И могу сказать, что на сегодня уже могу поправить то, что накосячили до меня программисты со стажем лет пять, а так же снять ограничения в связи с бывшей малой скоростью обработки. Мой код работает быстрее на порядок.
"... а ещё я крестиком вышивать умею.."

И вновь возвёл очи к небу..


Название: Re: Регулярное выражение с QString
Отправлено: Igors от Июль 29, 2013, 11:48
В общем то мой код работает быстро.
Та неужели?  :)

Но хотелось бы увидеть тот код который предлагали. 
Пост #42 (хотя может и еще кто-то предлагал, разве в этой свалке разберешь)


Название: Re: Регулярное выражение с QString
Отправлено: Majestio от Июль 29, 2013, 11:49
И как это число соотносится с результатами, полученными на моём железе?  ???
Преобразовал перл скрипт в exe  - но имхо это не халяльно  :P
В виде exe у меня стал выдавать 3980-4120, ну как есть, так есть.
Качнуть можно отсюда - http://majestio.tk/soft/Test.7z (http://majestio.tk/soft/Test.7z).
Запускайте, смотрите...


Название: Re: Регулярное выражение с QString
Отправлено: m_ax от Июль 29, 2013, 11:51
И как это число соотносится с результатами, полученными на моём железе?  ???
Преобразовал перл скрипт в exe  - но имхо это не халяльно  :P
В виде exe у меня стал выдавать 3980-4120, ну как есть, так есть.
Качнуть можно отсюда - http://majestio.tk/soft/Test.7z (http://majestio.tk/soft/Test.7z).
Запускайте, смотрите...

У меня linux..


Название: Re: Регулярное выражение с QString
Отправлено: Majestio от Июль 29, 2013, 11:56
У меня linux..

Линух без Перла ???? 0_o


Название: Re: Регулярное выражение с QString
Отправлено: m_ax от Июль 29, 2013, 12:09
Вроде есть, да:
This is perl 5, version 14, subversion 2 (v5.14.2) built for x86_64-linux-gnu-thread-multi

Elapsed: 16.4409940242767
Это, полагаю, в секундах.. Против моего 9.028

Всё понятно)


Название: Re: Регулярное выражение с QString
Отправлено: Majestio от Июль 29, 2013, 12:15
Вроде есть, да:
This is perl 5, version 14, subversion 2 (v5.14.2) built for x86_64-linux-gnu-thread-multi

Elapsed: 16.4409940242767
Это, полагаю, в секундах.. Против моего 9.028

Всё понятно)

Мистика .... если взять выполнение моего кода на (Ц++) на моем компьютере (34843) и его же у вас (17590) - следует, что скорость вашего "аппарата" в два раза вышей, чем у меня.

Теперь вопрос, как код, который выполняется у меня 3-4 секунды выполняется у вас 16, если скорость, как мы выяснили - почти в два раза выше?

???

ЗЫ: Когда тестировал, немного изменил строчку на
Код:
$Elapsed = int((gettimeofday() - $Start)*1000); 
Чтобы выводило в милисек. Но не суть, результаты ппц нелогичные. Щя запущу виртуальную машину, и запущу под Linux, FreeBSD, Mac OS X ... как-то это все подозрительно)))


Название: Re: Регулярное выражение с QString
Отправлено: m_ax от Июль 29, 2013, 12:23

Мистика .... если взять выполнение моего кода на (Ц++) на моем компьютере (34843) и его же у вас (17590) - следует, что скорость вашего "аппарата" в два раза вышей, чем у меня.


Нет, из этого ещё не следует.. Ещё от компилятора и его опций зависит.. (так то комп у меня слабенький, по современным меркам) А также от загруженности процессора на момент запуска тестов и ещё, наверное, от туевой хучи чего)



Название: Re: Регулярное выражение с QString
Отправлено: Majestio от Июль 29, 2013, 12:56
Стоп ... Если и мой код, и код Old'а - у вас выполняется в два раза быстрее, чем и у меня и у него... Тогда не понимаю, откуда такое ускорение исполняемых файлов и торможение Perl ...

По поводу Perl'а под другими осями:


FreeBSD

(http://s2.ipicture.ru/uploads/20130729/88RwxScC.png) (http://s2.ipicture.ru/uploads/20130729/736qT764.png)

Linux

(http://s2.ipicture.ru/uploads/20130729/9JZsevNO.png) (http://s2.ipicture.ru/uploads/20130729/4k7FYN1c.png)


Mac OS X

(http://s2.ipicture.ru/uploads/20130729/bN2reAhC.png) (http://s2.ipicture.ru/uploads/20130729/Aybq3xm1.png)


Название: Re: Регулярное выражение с QString
Отправлено: Majestio от Июль 29, 2013, 13:03
Нет, из этого ещё не следует.. Ещё от компилятора и его опций зависит..

Ну вы же выставляли одинаковые опции для всех трех тестов?
Значит соотнесение времен выполнения - достоверное?
Не имея буста на борту - код Old'а и свой я тоже исполнял с одинаковыми опциями.

Вывод: не вдаваясь в сами милисекунды - мы можем судить о пропорциях скоростей? Соответственно, я имею право на основании "своих" скоростей кода на Ц++ сравнивать и производительность и Perl-кода?


Название: Re: Регулярное выражение с QString
Отправлено: Majestio от Июль 29, 2013, 13:36
Похоже я немного понял, где собака зарылась, если покажите мне скрин результата работы Перл-скрипта.
Есть там матюки по поводу Wide Strings?

Скорее всего дело в неполной поддержке UTF-8 в вашей версии Perl. Подробнее - тут (http://blog.truecrux.org/post/xxvi). В моей все ок.


Название: Re: Регулярное выражение с QString
Отправлено: m_ax от Июль 29, 2013, 13:37
Нет, из этого ещё не следует.. Ещё от компилятора и его опций зависит..

Ну вы же выставляли одинаковые опции для всех трех тестов?
Значит соотнесение времен выполнения - достоверное?
Не имея буста на борту - код Old'а и свой я тоже исполнял с одинаковыми опциями.

Да, соотношение для всех трёх тестов достоверно) Т.е. фактически надо сравнивать не абсолютные значения а относительные.
И эти отношения для c++ кода у нас с Old'ом примерно совпадают..

Цитировать
Вывод: не вдаваясь в сами милисекунды - мы можем судить о пропорциях скоростей?
Можем, но только сравнивая относительные значения полученные на конкретном железе.

Цитировать
Соответственно, я имею право на основании "своих" скоростей кода на Ц++ сравнивать и производительность и Perl-кода?
Можете, если запустите perl код и два c++ теста в равных условиях)

Прилагаю два скриншота с запуском вашего test.pl и test.cpp..

Результаты там такие:
С++:
Old:            18470 15211
Majestio:    23696 15211
m_ax:    12876 15211

Perl:
Elapsed: 14575


Название: Re: Регулярное выражение с QString
Отправлено: Majestio от Июль 29, 2013, 13:43
Убегаю по делам. Если не трудно - приаттачьте свой Ц++ проект для теста. Приду, погоняю.
(Свою часть с бустом ток вырежьте - нет его у меня), буду ориентироваться на часть своего кода, и кода Old'а.


Название: Re: Регулярное выражение с QString
Отправлено: m_ax от Июль 29, 2013, 13:51
Погоняйте, погоняйте)


Название: Re: Регулярное выражение с QString
Отправлено: Spark от Июль 29, 2013, 18:11
"... а ещё я крестиком вышивать умею.."

И вновь возвёл очи к небу..
Я механик и действительно много чего умею. Ну например реставрировать машину и покрасить.
Сами напросились.
Та неужели?  :)
Не медленнее чем у участников соревнования, в рамках QT.
В любом случае самое тонкое место:
Код
C++ (Qt)
itemList = originalText.split(QRegExp("[^a-z]"),QString::SkipEmptyParts);
И это присутствует у всех. Поэтому соревнования как таковые в общем то бессмысленны, опять же в рамках QT.
Если приспичит то надо пробовать иные способы разделения текста. Но в общем то это уже больше ради спортивного интереса. Если кому и придет  в голову обрабатывать такие объемы, то подождет 15 секунд.
Другое дело - у меня тормозит вывод на экран. Но это придется разбираться с чужой функцией, что не так и можно ли улучшить.


Название: Re: Регулярное выражение с QString
Отправлено: Igors от Июль 29, 2013, 18:23
Я механик и действительно много чего умею. Ну например реставрировать машину и покрасить.
Ну вот и делайте то что умеете. Я напр очень люблю слушать музыку, но не обладаю слухом и чувством ритма. Ну я же не пытаюсь доказать другим что я "тоже музыкант"  :)


Название: Re: Регулярное выражение с QString
Отправлено: Majestio от Июль 29, 2013, 18:27
Погоняйте, погоняйте)

Получите и распишитесь! 

(http://s2.ipicture.ru/uploads/20130729/DRhZnc5e.png) (http://s2.ipicture.ru/uploads/20130729/v3xNWX6S.png)

;D



Название: Re: Регулярное выражение с QString
Отправлено: m_ax от Июль 29, 2013, 18:32
Мне показалось, или вы сравниваете результаты с debug версией?
Надо в релизе тесты гонять  ;)


Название: Re: Регулярное выражение с QString
Отправлено: Majestio от Июль 29, 2013, 19:03
Мне показалось, или вы сравниваете результаты с debug версией?
Надо в релизе тесты гонять  ;)

Да не, все равно какая-то мистика ... см. под маком:

(http://s2.ipicture.ru/uploads/20130729/HVcT5WI1.png) (http://s2.ipicture.ru/uploads/20130729/ETUAm2mT.png)

Хотя компиляторы разные, под Mac OS X - Clang, но все равно...


Название: Re: Регулярное выражение с QString
Отправлено: m_ax от Июль 29, 2013, 19:06
Нет там никакой мистики..
А под виндой в релизе какие результаты?



Название: Re: Регулярное выражение с QString
Отправлено: Majestio от Июль 29, 2013, 19:11
Нет там никакой мистики..
А под виндой в релизе какие результаты?
Щя повторю тест под вынью...Под релизом.


Название: Re: Регулярное выражение с QString
Отправлено: Majestio от Июль 29, 2013, 19:17
Вот под вынью под релизом:

(http://s2.ipicture.ru/uploads/20130729/Q46v0ZGS.png)

Первые два запуска с опцией С++11, в третьем на всяк случай выключил.
Да быстрее - но под маком все равно в 2.5 раза быстрее.
Перл везде показывает стабильные цифры, на скринах видно.


Название: Re: Регулярное выражение с QString
Отправлено: Majestio от Июль 29, 2013, 19:36
Линух ваще удивил:

(http://s2.ipicture.ru/uploads/20130729/3aF6FXLM.png) (http://s2.ipicture.ru/uploads/20130729/3GT3tdre.png)

Хотя Perl - как всегда быстро и стабильно  ;D

Лан, забиваю с экспериментами ... что хотел сказать про регулярки и их "естественное" использование - я сказал.  8)



Название: Re: Регулярное выражение с QString
Отправлено: Old от Июль 29, 2013, 19:41
Хотя Perl - как всегда быстро и стабильно  ;D
Перл быстр, потому что работает с UTF8, в отличие от нас.
Хотя посмотрел тестовый файл - там все на кириллице, коды их в unicode помещаются в short, то на то и выходит.


Название: Re: Регулярное выражение с QString
Отправлено: Majestio от Июль 29, 2013, 20:00
Перл быстр, потому что работает с UTF8, в отличие от нас.

Ну я попробовал прописывать "кодеки", типа:

Код
C++ (Qt)
QTextCodec *codec = QTextCodec::codecForName("UTF-8");
QTextCodec::setCodecForLocale(codec);
 

Легче не стало ... (под вынь)

Old:    9578 15211
Majestio:    12047 15211



Вдогоночку ....

Изменил кодировку под win-1251 ...

Old:    8985 247
Majestio:    11593 247
Perl: 3312 15211

Ну вот кагбэ так  ::)


Название: Re: Регулярное выражение с QString
Отправлено: Old от Июль 29, 2013, 20:06
Ну я попробовал прописывать "кодеки"
Дело не в этом, QString всегда хранит строку в unicode, а это минимум 16 бит на символ, а так и все 32 бита. А в utf8 латинские символы занимают 8 бит, а кириллица 16 бит.
Т.е. если бы в тексте было много латиницы, то перлу пришлось бы меньше молотить.


Название: Re: Регулярное выражение с QString
Отправлено: Majestio от Июль 29, 2013, 20:07
Ну я попробовал прописывать "кодеки"
Дело не в этом, QString всегда хранит строку в unicode, а это минимум 16 бит на символ, а так и все 32 бита. А в utf8 латинские символы занимают 8 бит, а кириллица 16 бит.
Т.е. если бы в тексте было много латиницы, то перлу пришлось бы меньше молотить.

См. мой тест с 8-битной кодировкой выше.


Название: Re: Регулярное выражение с QString
Отправлено: Old от Июль 29, 2013, 20:10
См. мой тест с 8-битной кодировкой выше.
Это никак не меняет кодировку внутри QString, там по прежнему unicode.


Название: Re: Регулярное выражение с QString
Отправлено: Majestio от Июль 29, 2013, 20:30
См. мой тест с 8-битной кодировкой выше.
Это никак не меняет кодировку внутри QString, там по прежнему unicode.

Меняет способ. И, по идее, ускоряет (что и видно по последнему тесту).
Из доки:

Цитировать
QString хранит строку 16-битных QChar, где каждый QChar хранит символ Unicode 4.0.

UTF-8 "неудобно" обрабатывается, т.к. - это кодировка с переменной длиной символа. Предоставляя текст в win-1251, даем возможность компилятору и фреймворку тупо проецировать любой индекс строки - как двойное смещение отностиельно однобайтного способа кодирования.

А вот почему перл выигрывает - это как раз по другой причине ))) Внимательно сравните два кода Ц++ и Perl, и примите во внимание что регэкспы для Перла - это стандарт языка, а не внешняя либа. И наверняка станет понятно  :P Готов подсказать  :P





Название: Re: Регулярное выражение с QString
Отправлено: Old от Июль 29, 2013, 20:40
Меняет способ.
Способ чего?
Можно устанавливать любые кодеки, это ничего не поменяет. Как был внутри unicode, так и остался.
А вот как произойдет конвертация в этот unicode из других кодировок и будет ли она правильная вопрос.


Название: Re: Регулярное выражение с QString
Отправлено: Majestio от Июль 29, 2013, 20:47
Способ чего?
Можно устанавливать любые кодеки, это ничего не поменяет. Как был внутри unicode, так и остался.
А вот как произойдет конвертация в этот unicode из других кодировок и будет ли она правильная вопрос.
Ну как чего, способа доступа к n-му символу строки. Для строки в Unicode - символ берется по смещению = 2*порядковый_номер_символа. Для UTF-8 берется посредством последовательной предварительной индексации (см. вики (http://ru.wikipedia.org/wiki/UTF-8)). А это дополнительное время.


Название: Re: Регулярное выражение с QString
Отправлено: Old от Июль 29, 2013, 20:56
Ну как чего, способа доступа к n-му символу строки. Для строки в Unicode - символ берется по смещению = 2*порядковый_номер_символа. Для UTF-8 берется посредством последовательной предварительной индексации (см. вики (http://ru.wikipedia.org/wiki/UTF-8)). А это дополнительное время.
Давайте вы сейчас посмотрите все вики и перечитаете последние посты. Вы уже не туда куда то пошли. ;)


Название: Re: Регулярное выражение с QString
Отправлено: Old от Июль 29, 2013, 21:18
Вам не кажется странным, что изменились количества слов: :)

Old:    9578 15211
Majestio:    12047 15211


Вдогоночку ....

Изменил кодировку под win-1251 ...

Old:    8985 247
Majestio:    11593 247
Perl: 3312 15211

Ну вот кагбэ так  ::)


Название: Re: Регулярное выражение с QString
Отправлено: Majestio от Июль 29, 2013, 21:35
Давайте вы сейчас посмотрите все вики и перечитаете последние посты. Вы уже не туда куда то пошли. ;)

Речь зашла об этом:

Перл быстр, потому что работает с UTF8, в отличие от нас.

А это ошибочное утверждение! У Перла есть средства для работы с UTF-8, и это совсем не родная его кодировка! Но и у Qt средства тоже есть. Вопрос в их реализациях. Перл не хранит текст в UTF-8, но и не хранит в Unicode. Про его механизм хорошим доступным языком написано тут (http://habrahabr.ru/post/53578/). Так что, как реализовали - так и пользуем.

Вам не кажется странным, что изменились количества слов: :)

Ничего странного ))) Перекодировочку забыл  ::) ... исправляю:

Код
C++ (Qt)
...
   QTextCodec *codec = QTextCodec::codecForName("CP-1251");
   QTextCodec::setCodecForLocale(codec);
 
   QFile in( "C:/Projects/wordstat/test.txt" );
   if( !in.open( QIODevice::ReadOnly | QIODevice::Text ) )
   {
       qWarning( "Test file not found." );
       return 1;
   }
 
   QTextStream inStream(&in);
   QString src = inStream.readAll();
...
 

Результаты:

Old:    8997 15211
Majestio:    11810 15211

Как видно, "от перемены мест слагаемых - легче не становится" )))


Название: Re: Регулярное выражение с QString
Отправлено: Majestio от Июль 29, 2013, 21:41
А вот по поводу регэкспов немного расскажу (Гурам - не читать!!!)  ::)

Что такое регэкспы? Регэксп - по сути реализация детерминированного конечного автомата (ДКА) для обработки массива символов. Таким образом, использование его состоит из двух фаз:

1) Непосредственное построение самого ДКА по регулярному выражению
2) Применение ДКА для обработки ваших данных

Почему приведенный мною пример на Перле быстрее? Дело не в регэкспах, а в их реализации. В Перле весь код, за исключением функции eval походит предварительную компиляцию в байт-код, потом его интерпретацию. На этой фазе предварительной компиляции, строятся и ДКА. Если не ошибаюсь, в ранних версиях Перл'а этого не было, но была функция "обучения" learn, которая и строила ДКА для множественного применения. Сейчас не получается раскопать, а старый файлец hlp-формата 97 года моя вынь не желает читать, без проверки на валидность))) Да ланна, не суть.

Что мы видим в коде на Ц++?
В середине цикла объявляется переменная локальной видимости QRegExp rx( "[\\s\\.,:;\\-()]" ), которая в каждом такте цикла строит для себя ДКА. Уверен, если ее вынести выше за цикл со 100-ми повторениями - Ц++ код станет заметно быстрее, а по "справедливости" - равным коду на Перл.


Название: Re: Регулярное выражение с QString
Отправлено: Old от Июль 29, 2013, 21:58
Речь зашла об этом:
Речь зашла о том, что в Qt все строки хранятся в unicode и не зависимо от того, какие кодеки мы куда устанавливаем, в конце концов разбор идет именно юникода. Всегда.

Как видно, "от перемены мест слагаемых - легче не становится" )))
Вы живете в чудесном мире, а у меня подобное шаманство никакого эффекта не вызывает.
Хоть локаль меняй, хоть в QTextStream кодек устанавливай. Грустно, но у меня Qt работает согласно документации.


Название: Re: Регулярное выражение с QString
Отправлено: Majestio от Июль 29, 2013, 22:03
Вы живете в чудесном мире, а у меня подобное шаманство никакого эффекта не вызывает.
Хоть локаль меняй, хоть в QTextStream кодек устанавливай. Грустно, но у меня Qt работает согласно документации.
Все возможно. От компиляции к компиляции цифры "пляшут". Тем не менее пример был не для этого. Я показывал соотнесение величин скоростей кода Ц++ и Перла на одной виртуальной машине в одинаковых условиях. Возможно с кодеками все именно так, как вы утверждаете. Тут спорить не хочу - значит это была случайность.  Но и "внутренности" Перла ("работает с UTF") в этом плане не совсем очевидны. По описаниям - флаги, адаптация, распозавание ... Одна вода.


Название: Re: Регулярное выражение с QString
Отправлено: Old от Июль 30, 2013, 09:25
Уверен, если ее вынести выше за цикл со 100-ми повторениями - Ц++ код станет заметно быстрее, а по "справедливости" - равным коду на Перл.
Уверены? Тогда вынесите и проверьте. К сожалению особо ничего не измениться, выигрыш будет меньше 1%.
Если посмотреть тесты производительности для разных библиотек регулярных выражений, то можно увидеть, что скорости у них очень отличаются, иногда на несколько порядков. А то, что в перле используется одна из самых быстрых (если не самая быстрая) библиотека - сомнений нет. Для перла это основная функция.


Название: Re: Регулярное выражение с QString
Отправлено: Majestio от Июль 30, 2013, 10:55
Уверены? Тогда вынесите и проверьте. К сожалению особо ничего не измениться, выигрыш будет меньше 1%.

В нашем случае - прирост еле заметен, гораздо меньше 1%, вы правы. Но и регэксп у нас совсем детский. Сейчас на вскидку не помню где мое добро - как-то писал на Перле конвертер слабо-структурированных текстов (нормативные акты законодательства). Приходилось делать регэкспы на страничку-две программного кода. Там это действительно было заметно.

Если посмотреть тесты производительности для разных библиотек регулярных выражений, то можно увидеть, что скорости у них очень отличаются, иногда на несколько порядков. А то, что в перле используется одна из самых быстрых (если не самая быстрая) библиотека - сомнений нет. Для перла это основная функция.

На счет скорости - утверждать сложно, статистики нет. Но то, что Перл - "законодатель моды" в рег экспах (читаем, наиболее полная реализация функционала регэкспов), это - к гадалке не ходи.


Название: Re: Регулярное выражение с QString
Отправлено: Spark от Июль 31, 2013, 17:41
Режим без сортировки (в порядке встречаемости) не получается. QHash все равно как то переворачивает текст. Для этого режима пришлось оформить старый код (первоначально мной предложенный). Режим необходим, но скорее для малых объемов, поэтому ничего страшного нет, но хотелось бы победить и эту проблему.
Может будут предложения, советы?


Название: Re: Регулярное выражение с QString
Отправлено: Spark от Июль 31, 2013, 19:45
Пока такой код выстроил.
Вариант2:
Код
C++ (Qt)
   QHash<QString, int> frequencyHash;
   foreach (QString Item, itemList) ++frequencyHash[Item];
   itemList.removeDuplicates();
   int countItem(0);
        foreach (QString trimmedStr, itemList)
        {
            countItemFull = countItemFull + frequencyHash.value(trimmedStr);
            countItem = frequencyHash.value(trimmedStr);
            countItemString.setNum(countItem);
 
            trimmedStr = trimmedStr + "\t" + countItemString;
            frequencyList.prepend( trimmedStr );
        }
Все-ж таки пошустрее.
Посоревнуйтесь :).


Название: Re: Регулярное выражение с QString
Отправлено: Spark от Август 01, 2013, 02:42
Однако, Вариант2 на порядок медленней, чем основной. Вроде бы нет многократного перебора текста и нет дополнительных регеспов, но Qlist строится медленно.


Название: Re: Регулярное выражение с QString
Отправлено: Igors от Август 01, 2013, 09:35
Зачем Вы подсчитываете countItemFull если он известен и равен itemList.size() до removeDuplicates. Записать можно значительно короче
Код
C++ (Qt)
 
foreach (QString s, itemList)
 frequencyList.prepend(s + "\t" + QString::Number(frequencyHash[s]));
 
Это вывод слов в начальном (или обратном) порядке но без повторов. Какой в нем смысл - хз.

Посоревнуйтесь :).
Вам до тех соревнований еще очень далеко. Лучше подумайте как организовать 2 и более вариантов вместе (сейчас будет "страшнэ")

Ну и конечно, порция нравоучений :) Нормально начинать с задачек типа таких
Цитировать
Написать ф-цию
int GetWordCount( const char * str );
которая возвращает число слов в строке str разделенных пробелами или табами.
Вот отсюда растут ноги. Вот это должен в первую очередь уметь программист. Однако наш колобок считает что он сможет проскочить и обойтись без всяких базовых умений. В результате он боится и всячески избегает написать свою ф-цию, класс, файл - зато охотно питается "плюшками" типа foreach, regexp и.т.п. Когда ему об этом мягко говорят - ну, в общем, видели  :)


Название: Re: Регулярное выражение с QString
Отправлено: Spark от Август 01, 2013, 09:52
Я не собирался с вами соревноваться. Я хотел, что бы вы посоревновались. Вы ведь это любите :).

Я работаю над собой :). У меня возникла проблема я ее решаю. Второй вариант проверил. Не лучше первого оказался на поверку. Сейчас испытываю третий. И т.д. Есть еще способы узнать, что лучше? Есть! Посоревнуйтесь :).
Но в общем то конечный результат, каким должен быть, известен. Будем искать способ решения.


Название: Re: Регулярное выражение с QString
Отправлено: Spark от Август 01, 2013, 09:58
Лучше подумайте как организовать 2 и более вариантов вместе (сейчас будет "страшнэ")
Не понял постановки задачи.
Сейчас у меня работают вместе три варианта сортировки. Два из них не хуже ваших. Третий работает медленно, но никто не предлагал решение. Ну и плюс уборка английского/русского/без уборки.  Размер, повторы.
(http://s018.radikal.ru/i512/1308/5f/682a03e887b7t.jpg) (http://radikal.ru/fp/a7038155f50247bcbbb6013cf3990be1)
В общем то сам модуль готов и прекрасно работает, но раз можно лучше, надо лучше.


Название: Re: Регулярное выражение с QString
Отправлено: kambala от Август 01, 2013, 11:24
писать слова без пробелов в интерфейсе — это не уважать пользователей. суть первых двух спинбоксов и кнопок непонятна.


Название: Re: Регулярное выражение с QString
Отправлено: Spark от Август 01, 2013, 11:35
Это тестовый вариант.
Спинбоксы ограничивают длину слова по количеству символов.
Ну а пара кнопок для того что бы пользователь быстро мог делать крайние ограничения:
Мах - 99 символов (фактически без ограничений)
Min  - MaxSizeWord = MinSazeWord

Однако и третий вариант не дал никаких преимуществ:
Код
C++ (Qt)
   // ВАРИАНТ3
   QHash<QString, int> frequencyHash;
   foreach (QString Item, itemList) ++frequencyHash[Item];
   itemList.removeDuplicates();
   QString IterW;
   QListIterator<QString> Iter(itemList);
   while(Iter.hasNext())
   {
       IterW = Iter.next();
       countItemFull = countItemFull + frequencyHash.value(IterW);
       countItemString.setNum(frequencyHash.value(IterW));
 
       trimmedStr = IterW + "\t" + countItemString;
       frequencyList.prepend( trimmedStr );
   }

Ладно видимо не в том направлении роем.
Будем искать.


Название: Re: Регулярное выражение с QString
Отправлено: kambala от Август 01, 2013, 12:11
вместо удаления дублей и прохода по списку можно просто пройтись конст_итератором по хэшу


Название: Re: Регулярное выражение с QString
Отправлено: Igors от Август 01, 2013, 13:48
Ладно видимо не в том направлении роем.
Будем искать.
Код
C++ (Qt)
QHash<QString, int> freqHash;
foreach (QString s, itemList) ++freqHash[s];
foreach (QString s, itemList) {
int & num = freqHash[s];
if (num < 0) continue;
frequencyList.prepend(s + '\t' + QString::Number(num));
num = -num;
}


Название: Re: Регулярное выражение с QString
Отправлено: Spark от Август 01, 2013, 13:49
вместо удаления дублей и прохода по списку можно просто пройтись конст_итератором по хэшу
Поставил счетчик. Удаление дублей оказалась, вроде, действительно то же не менее тормознутым процессом чем пословно искать, как это дела я в первом варианте. Я то думал, оптимизирована функция. И результаты схожи. Получается примерно одинаков алгоритм.
Сейчас подумаю над вашим вариантом. Хотя с хешитераторм и мапитератором экспериментровал. Перемешивают списки. Попробую конст_итератор.

В общем на очередное поругание:
Код
C++ (Qt)
void MainWindow::bufferButtonSave()
{
   QTime tm;
 
   tm.start();
 
   QClipboard *clipboard = QApplication::clipboard();
   QString originalText = clipboard->text();
   QString countItemFullString;
   QString countItemString, countItemStringZero;
   QStringList itemList;
   QStringList frequencyList;
   int countItemFull(0);
   int minSizeWord(cfg.preferences.minSizeWord);
   int maxSizeWord(cfg.preferences.maxSizeWord);
   int minRepeats(cfg.preferences.minRepeats);
 
   qDebug() << "Reade Data: " << tm.elapsed();
 
   tm.start();
 
   originalText = originalText.toLower();
 
   qDebug() << "Data toLower: " << tm.elapsed();
 
   textory.clear();
 
   tm.start();
 
   // ОСТАВЛЯЕМ ТЕКСТ
   if(cfg.preferences.langStatSort == 0)itemList = originalText.split(QRegExp("[\\s\\W\\d]+"),QString::SkipEmptyParts);
 
   // ОСТАВЛЯЕМ АНГЛИЙКИЙ
   if(cfg.preferences.langStatSort == 1)itemList = originalText.split(QRegExp("[^a-z]"),QString::SkipEmptyParts);
 
   // ОСТАВЛЯЕМ РУССКИЙ
   if(cfg.preferences.langStatSort == 2)itemList = originalText.split(QRegExp(QString::fromUtf8("[^а-яё]")),QString::SkipEmptyParts);
 
   qDebug() << "Data split1: " << tm.elapsed();
   tm.start();
 
   if(cfg.preferences.typeOfSort == 2)
   QHash<QString, int> frequencyHash;
   foreach (QString Item, itemList) ++frequencyHash[Item];
   itemList.removeDuplicates();
   QString IterW;
   QListIterator<QString> Iter(itemList);
   while(Iter.hasNext())
   {
       IterW = Iter.next();
       countItemFull = countItemFull + frequencyHash.value(IterW);
       countItemString.setNum(frequencyHash.value(IterW));
 
       trimmedStr = IterW + "\t" + countItemString;
       frequencyList.prepend( trimmedStr );
   }
 
   if(cfg.preferences.typeOfSort == 0 || cfg.preferences.typeOfSort == 1)
   {
       QHash<QString, int> frequencyHash;
       foreach (QString Item, itemList) ++frequencyHash[Item];
 
       qDebug() << "Data split2: " << tm.elapsed();
 
       tm.start();
 
       QHashIterator<QString,int> Iter(frequencyHash);
       while(Iter.hasNext())
       {
           Iter.next();
           countItemFull = countItemFull + Iter.value();
           if(Iter.key().size() < minSizeWord || Iter.key().size() > maxSizeWord || Iter.value() < minRepeats )continue;
           countItemString.setNum(Iter.value());
           countItemStringZero = countItemString;
           // ОРГАНИЗОВЫВАЕМ СОРТИРОВКУ
           countItemStringZero = QString("%1")
                   .arg(countItemString, 6, '0');
 
           if(cfg.preferences.typeOfSort == 0)frequencyList.append(countItemStringZero + "_" + Iter.key() + "\t" + countItemString );
           if(cfg.preferences.typeOfSort == 1 || cfg.preferences.typeOfSort == 2)frequencyList.prepend(Iter.key() + "\t" + countItemString );
       }
   }
 
 
   qDebug() << "Count: " << tm.elapsed();
 
   tm.start();
 
   // СТРОИМ СПИСОК
   if(cfg.preferences.typeOfSort != 2)qSort(frequencyList);
 
   textory.enableAdd( true );
 
   qDebug() << "Data sort: " << tm.elapsed();
 
   tm.start();
 
   if(cfg.preferences.typeOfSort == 0 || cfg.preferences.typeOfSort == 2)
   {
       foreach (QString itm, frequencyList)
       {
           if(cfg.preferences.typeOfSort == 0)itm.remove(0,7);
           textory.addItem( Textory::Item( 1, itm ) );
       }
   }
 
   if(cfg.preferences.typeOfSort == 1)
   {
       QListIterator<QString>itm(frequencyList);
       itm.toBack();
       while (itm.hasPrevious())
       textory.addItem( Textory::Item( 1, itm.previous() ) );
   }
 
   qDebug() << "Clear zero: " << tm.elapsed();
 
   tm.start();
 
   countItemFullString.setNum(countItemFull);
 
   ui.textoryPaneWidget->getTextoryLabel().setText( "Frequency list (" + countItemFullString + ")" );
 
   qDebug() << "Write name: " << tm.elapsed();
}


Название: Re: Регулярное выражение с QString
Отправлено: Spark от Август 01, 2013, 13:50
Ладно видимо не в том направлении роем.
Будем искать.
Код
C++ (Qt)
QHash<QString, int> freqHash;
foreach (QString s, itemList) ++freqHash[s];
foreach (QString s, itemList) {
int & num = freqHash[s];
if (num < 0) continue;
frequencyList.prepend(s + '\t' + QString::Number(num));
num = -num;
}

Спасибо сейчас оценим.


Название: Re: Регулярное выражение с QString
Отправлено: Spark от Август 01, 2013, 15:02
Igors Спасибо! Протестировал ваш код. Очень хорошо. На порядок быстрее чем то, что смог я сделать. Но на порядок (почти в 30раз) медленнее остальных вариантов (сортировка в порядке частотности и по алфавиту).
Наверное можно остановиться на этом :). Во всяком случае теперь не  придется час ждать вывода, если кому то понадобится проанализировать текст миллионов на пять слов. В штатном режиме тормоза не наблюдаются.
Аналоги считают из рук вон плохо. Стандартный функционал отработан. Теперь можно приступить к более крутой обработке.


Название: Re: Регулярное выражение с QString
Отправлено: Igors от Август 01, 2013, 17:19
Igors Спасибо! Протестировал ваш код. Очень хорошо. На порядок быстрее чем то, что смог я сделать. Но на порядок (почти в 30раз) медленнее остальных вариантов (сортировка в порядке частотности и по алфавиту).
Что-то Вы не так меряли - возможно все съедается на построении itemList, этот код я не видел. Кстати тут было замечание насчет reserve, оно справедливо и для QHash
Код
C++ (Qt)
QHash<QString, int> freqHash;
freqHash.reserve(itemList.size());  // так должно быть быстрее (правда хз насколько)
foreach (QString s, itemList) ++freqHash[s];
 


Название: Re: Регулярное выражение с QString
Отправлено: Spark от Август 01, 2013, 17:26
Сейчас счетчики выставлю и дам результаты. Может я чего недопонимаю.


Название: Re: Регулярное выражение с QString
Отправлено: kambala от Август 01, 2013, 17:52
2Igors: а почему foreach без константных ссылок?


Название: Re: Регулярное выражение с QString
Отправлено: Spark от Август 01, 2013, 18:09
Немного погорячился. Видимо сравнивал со старыми данными, после этого код пополнел. Но все таки на порядок.
В общем тестировал этот код:
Код
C++ (Qt)
void MainWindow::bufferButtonSave()
{
   QTime tm;
   tm.start();
 
   QClipboard *clipboard = QApplication::clipboard();
   QString originalText = clipboard->text();
   QString countItemFullString;
   QString countItemString, countItemStringZero;
   QStringList itemList;
   QStringList frequencyList;
   int countItemFull(0);
   int minSizeWord(cfg.preferences.minSizeWord);
   int maxSizeWord(cfg.preferences.maxSizeWord);
   int minRepeats(cfg.preferences.minRepeats);
 
   qDebug() << "Reade Data: " << tm.elapsed();
   tm.start();
 
   originalText = originalText.toLower();
 
   qDebug() << "Data toLower: " << tm.elapsed();
   tm.start();
 
   textory.clear();
 
   // ОСТАВЛЯЕМ ТЕКСТ
   if(cfg.preferences.langStatSort == 0)itemList = originalText.split(QRegExp("[\\s\\W\\d]+"),QString::SkipEmptyParts);
 
   // ОСТАВЛЯЕМ АНГЛИЙКИЙ
   if(cfg.preferences.langStatSort == 1)itemList = originalText.split(QRegExp("[^a-z]"),QString::SkipEmptyParts);
 
   // ОСТАВЛЯЕМ РУССКИЙ
   if(cfg.preferences.langStatSort == 2)itemList = originalText.split(QRegExp(QString::fromUtf8("[^а-яё]")),QString::SkipEmptyParts);
 
   qDebug() << "Data split1: " << tm.elapsed();
   tm.start();
 
   // ВАРИАНТ БЕЗ СОРТИРОВКИ (frequencyList)
   if(cfg.preferences.typeOfSort == 2)
   {
       QHash<QString, int> frequencyHash;
       foreach (QString s, itemList) ++frequencyHash[s];
       foreach (QString s, itemList)
       {
           int & num = frequencyHash[s];
           countItemString.setNum(num);
           if (num < 0) continue;
           countItemFull = countItemFull + num;
           if(s.size() < minSizeWord || s.size() > maxSizeWord || frequencyHash[s] < minRepeats )continue;
           frequencyList.prepend(s + '\t' + countItemString);
           num = -num;
       }
   }
 
   // СОРТИРОВКА В ПОРЯДКЕ ЧАСТОТНОСТИ И АЛФАВИТУ
   if(cfg.preferences.typeOfSort == 0 || cfg.preferences.typeOfSort == 1)
   {
       QHash<QString, int> frequencyHash;
       foreach (QString Item, itemList) ++frequencyHash[Item];
 
       QHashIterator<QString,int> Iter(frequencyHash);
       while(Iter.hasNext())
       {
           Iter.next();
           countItemFull = countItemFull + Iter.value();
           if(Iter.key().size() < minSizeWord || Iter.key().size() > maxSizeWord || Iter.value() < minRepeats )continue;
           countItemString.setNum(Iter.value());
           countItemStringZero = countItemString;
           // ОРГАНИЗОВЫВАЕМ СОРТИРОВКУ
           countItemStringZero = QString("%1")
                   .arg(countItemString, 6, '0');
 
           if(cfg.preferences.typeOfSort == 0)frequencyList.append(countItemStringZero + "_" + Iter.key() + "\t" + countItemString );
           if(cfg.preferences.typeOfSort == 1 || cfg.preferences.typeOfSort == 2)frequencyList.append(Iter.key() + "\t" + countItemString );
       }
   }
 
   qDebug() << "Count: " << tm.elapsed();
   tm.start();
 
   // СТРОИМ СПИСОК
   if(cfg.preferences.typeOfSort != 2)qSort(frequencyList);
 
   textory.enableAdd( true );
 
   qDebug() << "Data sort: " << tm.elapsed();
   tm.start();
 
   if(cfg.preferences.typeOfSort == 0 || cfg.preferences.typeOfSort == 2)
   {
       foreach (QString itm, frequencyList)
       {
           if(cfg.preferences.typeOfSort == 0)itm.remove(0,7);
           // textory.addItem( Textory::Item( 1, itm ) );
       }
   }
 
   if(cfg.preferences.typeOfSort == 1)
   {
       QListIterator<QString>itm(frequencyList);
       itm.toBack();
       while (itm.hasPrevious())
           // textory.addItem( Textory::Item( 1, itm.previous() ) );
   }
 
   qDebug() << "Clear zero: " << tm.elapsed();
   tm.start();
 
   countItemFullString.setNum(countItemFull);
 
   ui.textoryPaneWidget->getTextoryLabel().setText( "Frequency list (" + countItemFullString + ")" );
 
   qDebug() << "Write name: " << tm.elapsed();
}


Название: Re: Регулярное выражение с QString
Отправлено: Spark от Август 01, 2013, 18:17
Текст довольно сложный. Смешанный текст, с большим количеством мусора. Всего  5812355 слов.

ПО ЧАСТОТНОСТИ:
Reade Data:  8943
Data toLower:  310
Data split:  9624
Count:  4992
Data sort:  421
Clear zero:  296
Write name:  0

========================
ПО АЛФАВИТУ:
Reade Data:  8948
Data toLower:  311
Data split:  9702
Count:  4316
Data sort:  301
Clear zero:  0
Write name:  0

===================
БЕЗ СОРТИРОВКИ:
Reade Data:  8961
Data toLower:  308
Data split:  9716
Count:  16154
Data sort:  0
Clear zero:  11
Write name:  0

Но!


Название: Re: Регулярное выражение с QString
Отправлено: Spark от Август 01, 2013, 18:21
Если произведем сортировку. Оставим английский текст:

ПО ЧАСТОТНОСТИ:
Reade Data:  8906
Data toLower:  311
Data split:  15298
Count:  1524
Data sort:  90
Clear zero:  79
Write name:  0

========================
ПО АЛФАВИТУ:
Reade Data:  9009
Data toLower:  309
Data split:  15322
Count:  1351
Data sort:  68
Clear zero:  0
Write name:  0

===================
БЕЗ СОРТИРОВКИ:
Reade Data:  8861
Data toLower:  306
Data split:  15205
Count:  13837
Data sort:  0
Clear zero:  3
Write name:  0

Как бы тут уже на порядок разница.
Но может я что напутал. Однако вроде в коде за каждую часть отвечает свой раздел.


Название: Re: Регулярное выражение с QString
Отправлено: Spark от Август 01, 2013, 18:23
Справедливости ради. Мой код считал этот тест минут 70-80 :). Хотя этот тест я может и не дождался. Английский он выделял примерно это время :).


Название: Re: Регулярное выражение с QString
Отправлено: Spark от Август 01, 2013, 18:26
Igors Спасибо! Протестировал ваш код. Очень хорошо. На порядок быстрее чем то, что смог я сделать. Но на порядок (почти в 30раз) медленнее остальных вариантов (сортировка в порядке частотности и по алфавиту).
Что-то Вы не так меряли - возможно все съедается на построении itemList, этот код я не видел. Кстати тут было замечание насчет reserve, оно справедливо и для QHash
Код
C++ (Qt)
QHash<QString, int> freqHash;
freqHash.reserve(itemList.size());  // так должно быть быстрее (правда хз насколько)
foreach (QString s, itemList) ++freqHash[s];
 
Спасибо учту и протестирую на сколько быстрее.
Но это какой то спортивный азарт :). Вовсе не думал, что в таких объемах кто то будет сортировать текст. Но все возможно. Дальше будет интереснее :). Пока это только стандартный функционал, но довольно полный. Встречал только одну программку с таким функционалом. Остальные урезаны.


Название: Re: Регулярное выражение с QString
Отправлено: Spark от Август 01, 2013, 18:31
Есть пара багов.
- Что то напутал с подсчетом общего количества слов.
- Если куда скопировать текст, а затем попробовать подсчитать русский в моей программе, то либо крякозябры, либо пусто.


Название: Re: Регулярное выражение с QString
Отправлено: Spark от Август 01, 2013, 18:49
Как бы резервирование особо ничего не дало:
Код
C++ (Qt)
   // ВАРИАНТ БЕЗ СОРТИРОВКИ (frequencyList)
   if(cfg.preferences.typeOfSort == 2)
   {
       QHash<QString, int> frequencyHash;
       frequencyHash.reserve(itemList.size());
       foreach (QString s, itemList) ++frequencyHash[s];
       foreach (QString s, itemList)
       {
           int & num = frequencyHash[s];
           countItemString.setNum(num);
           if (num < 0) continue;
           countItemFull = countItemFull + num;
           if(s.size() < minSizeWord || s.size() > maxSizeWord || frequencyHash[s] < minRepeats )continue;
           frequencyList.prepend(s + '\t' + countItemString);
           num = -num;
       }
   }

Результаты при подсчете всех слов:
Reade Data:  8933
Data toLower:  311
Data split:  9620
Count:  15837
Data sort:  0
Clear zero:  12
Write name:  0

Английских:
Reade Data:  8971
Data toLower:  310
Data split:  15264
Count:  13536
Data sort:  0
Clear zero:  4
Write name:  0


Название: Re: Регулярное выражение с QString
Отправлено: Igors от Август 01, 2013, 19:49
Код
C++ (Qt)
 
if(s.size() < minSizeWord || s.size() > maxSizeWord || frequencyHash[s] < minRepeats )continue;
 
Избегайте таких слишком длинных строк. И пробелы ставьте однообразно (напр после if).
Код
C++ (Qt)
 
frequencyList.reserve(itemList.size()); // ну "типа грамотно"
foreach (QString s, itemList)  {
 if (s.size() < minSizeWord || s.size() > maxSizeWord) continue;   // сначала проверились по длине
 int & num = frequencyHash[s];
 if (num < 0) continue;
 if (num >= minRepeats ) {
  countItemFull += num;
  frequencyList.prepend(s + '\t' + QString::number(long(num));
 }
 num = -num;
}
 
Пользуйnесь QString::number, не плодите ненужных переменных.


Название: Re: Регулярное выражение с QString
Отправлено: Spark от Август 02, 2013, 02:45
Код:
[quote author=Igors link=topic=25332.msg181725#msg181725 date=1375375776]
Избегайте таких слишком длинных строк. И пробелы ставьте однообразно (напр после if).

Пользуйnесь QString::number, не плодите ненужных переменных.
[/quote]
Спасибо за поправки. По поводу QString::number, пробовал использовать как в вашем коде, компилятор ругается. Особо не вникал в причины, поставил как работает. Сейчас попробую разобраться.


Название: Re: Регулярное выражение с QString
Отправлено: Spark от Август 02, 2013, 03:40
Спасибо! Поправил:
Код
C++ (Qt)
   // ВАРИАНТ БЕЗ СОРТИРОВКИ (frequencyList)
   if(cfg.preferences.typeOfSort == 2)
   {
       QHash<QString, int> frequencyHash;
       frequencyList.reserve(itemList.size());
       foreach (QString s, itemList) {
           if(s.size() < minSizeWord || s.size() > maxSizeWord )continue;
           int & num = frequencyHash[s];
           if (num < 0) continue;
           if(num >= minRepeats ) {
               countItemFull += num;
               frequencyList.prepend(s + '\t' + QString::number(long(num)));
           }
           num = -num;
       }
   }

Результаты при подсчете всех слов:
Reade Data:  8807
Data toLower:  307
Data split:  9405
Count:  4111
Data sort:  0
Clear zero:  11
Write name:  0

Английских:
Reade Data:  8763
Data toLower:  306
Data split:  15077
Count:  1334
Data sort:  0
Clear zero:  4
Write name:  0

Фактически уравнены расчеты с остальными вариантами.

========================
Для сравнения старые данные http://www.prog.org.ru/index.php?topic=25332.msg181717#msg181717:
Результаты при подсчете всех слов:
Reade Data:  8933
Data toLower:  311
Data split:  9620
Count:  15837
Data sort:  0
Clear zero:  12
Write name:  0

Английских:
Reade Data:  8971
Data toLower:  310
Data split:  15264
Count:  13536
Data sort:  0
Clear zero:  4
Write name:  0

Но показалось, что при этом считает не верно. Ладно прибегу с работы перепроверю условия.


Название: Re: Регулярное выражение с QString
Отправлено: Spark от Август 02, 2013, 16:40
Зачем Вы подсчитываете countItemFull если он известен и равен itemList.size() до removeDuplicates. Записать можно значительно короче
Ухудшила результат на 5 секунд.
На сколько понял это лишняя пробежка по списку.


Название: Re: Регулярное выражение с QString
Отправлено: Spark от Август 02, 2013, 17:09
Можно ли табуляцию увеличить на определенное число символов?


Название: Re: Регулярное выражение с QString
Отправлено: Spark от Август 02, 2013, 17:54
На это момент код выглядит так:
Код
C++ (Qt)
void MainWindow::bufferButtonSave()
{
   QTime tm;
   tm.start();
 
   QClipboard *clipboard = QApplication::clipboard();
   QString originalText = clipboard->text();
   QString countItemFullString;
   QString countItemStringZero;
   QStringList itemList;
   QStringList frequencyList;
   int countItemFull(0);
   int minSizeWord(cfg.preferences.minSizeWord);
   int maxSizeWord(cfg.preferences.maxSizeWord);
   int minRepeats(cfg.preferences.minRepeats);
 
   qDebug() << "Reade Data: " << tm.elapsed();
 
   tm.start();
   originalText = originalText.toLower();
 
   qDebug() << "Data toLower: " << tm.elapsed();
   tm.start();
 
   textory.clear();
 
   // ОСТАВЛЯЕМ ТЕКСТ
   if(cfg.preferences.langStatSort == 0)itemList = originalText.split(QRegExp("[\\s\\W\\d]+"),QString::SkipEmptyParts);
 
   // ОСТАВЛЯЕМ АНГЛИЙКИЙ
   if(cfg.preferences.langStatSort == 1)itemList = originalText.split(QRegExp("[^a-z]"),QString::SkipEmptyParts);
 
   // ОСТАВЛЯЕМ РУССКИЙ
   if(cfg.preferences.langStatSort == 2)itemList = originalText.split(QRegExp(QString::fromUtf8("[^а-яё]")),QString::SkipEmptyParts);
 
   countItemFull = itemList.size();
 
   qDebug() << "Data split: " << tm.elapsed();
   tm.start();
 
   // ВАРИАНТ БЕЗ СОРТИРОВКИ (frequencyList)
   if(cfg.preferences.typeOfSort == 2)
   {
       QHash<QString, int> frequencyHash;
       foreach (QString s, itemList) ++frequencyHash[s];
       frequencyList.reserve(countItemFull);
       foreach (QString s, itemList) {
           if(s.size() < minSizeWord || s.size() > maxSizeWord )continue;
           int & num = frequencyHash[s];
           if (num < 0) continue;
           if(num >= minRepeats ) {
               frequencyList.prepend(s + '\t' + QString::number(long(num)));
           }
           num = -num;
       }
   }
 
   // СОРТИРОВКА В ПОРЯДКЕ ЧАСТОТНОСТИ И АЛФАВИТУ
   if(cfg.preferences.typeOfSort == 0 || cfg.preferences.typeOfSort == 1)
   {
       QHash<QString, int> frequencyHash;
       foreach (QString Item, itemList) ++frequencyHash[Item];
       frequencyList.reserve(countItemFull);
       QHashIterator<QString,int> Iter(frequencyHash);
       while(Iter.hasNext())
       {
           Iter.next();
           if(Iter.key().size() < minSizeWord || Iter.key().size() > maxSizeWord || Iter.value() < minRepeats )continue;
           countItemStringZero = QString::number(long(Iter.value())).rightJustified(6, '0');
           if(cfg.preferences.typeOfSort == 0)frequencyList.append(countItemStringZero + Iter.key() + "\t" + QString::number(long(Iter.value())) );
           if(cfg.preferences.typeOfSort == 1 || cfg.preferences.typeOfSort == 2)frequencyList.append(Iter.key() + "\t" + QString::number(long(Iter.value())) );
       }
   }
 
   qDebug() << "Count: " << tm.elapsed();
   tm.start();
 
   // СТРОИМ СПИСОК
   if(cfg.preferences.typeOfSort != 2)qSort(frequencyList);
 
   textory.enableAdd( true );
 
   qDebug() << "Data sort: " << tm.elapsed();
   tm.start();
 
   if(cfg.preferences.typeOfSort == 0 || cfg.preferences.typeOfSort == 2)
   {
       foreach (QString itm, frequencyList)
       {
           if(cfg.preferences.typeOfSort == 0)itm.remove(0,6);
           textory.addItem( Textory::Item( 1, itm ) );
       }
   }
 
   if(cfg.preferences.typeOfSort == 1)
   {
       QListIterator<QString>itm(frequencyList);
       itm.toBack();
       while (itm.hasPrevious())
           textory.addItem( Textory::Item( 1, itm.previous() ) );
   }
 
   qDebug() << "Clear zero: " << tm.elapsed();
   tm.start();
 
   countItemFullString.setNum(countItemFull);
 
   ui.textoryPaneWidget->getTextoryLabel().setText( "Frequency list (" + countItemFullString + ")" );
 
   qDebug() << "Write name: " << tm.elapsed();
}
Ждем очередную порцию взбучки :).


Название: Re: Регулярное выражение с QString
Отправлено: Spark от Август 02, 2013, 18:40
Как мог оптимизировал:
Код
C++ (Qt)
void MainWindow::bufferButtonSave()
{
   QTime tm;
   tm.start();
 
   QClipboard *clipboard = QApplication::clipboard();
   QString originalText = clipboard->text();
   QString countItemFullString;
   QString countItemStringZero;
   QStringList itemList;
   QStringList frequencyList;
   int countItemFull(0);
   int minSizeWord(cfg.preferences.minSizeWord);
   int maxSizeWord(cfg.preferences.maxSizeWord);
   int minRepeats(cfg.preferences.minRepeats);
 
   qDebug() << "Reade Data: " << tm.elapsed();
 
   tm.start();
   originalText = originalText.toLower();
 
   qDebug() << "Data toLower: " << tm.elapsed();
   tm.start();
 
   textory.clear();
 
   // ОСТАВЛЯЕМ ТЕКСТ
   if(cfg.preferences.langStatSort == 0)itemList = originalText.split(QRegExp("[\\s\\W\\d]+"),QString::SkipEmptyParts);
 
   // ОСТАВЛЯЕМ АНГЛИЙКИЙ
   if(cfg.preferences.langStatSort == 1)itemList = originalText.split(QRegExp("[^a-z]"),QString::SkipEmptyParts);
 
   // ОСТАВЛЯЕМ РУССКИЙ
   if(cfg.preferences.langStatSort == 2)itemList = originalText.split(QRegExp(QString::fromUtf8("[^а-яё]")),QString::SkipEmptyParts);
 
   countItemFull = itemList.size();
 
   qDebug() << "Data split: " << tm.elapsed();
   tm.start();
 
   // СОРТИРОВКА (frequencyList)
       QHash<QString, int> frequencyHash;
       foreach (QString s, itemList) ++frequencyHash[s];
       frequencyList.reserve(countItemFull);
       foreach (QString s, itemList) {
           if(s.size() < minSizeWord || s.size() > maxSizeWord )continue;
           int & num = frequencyHash[s];
           if (num < 0) continue;
           if(num >= minRepeats ) {
               if(cfg.preferences.typeOfSort == 2)frequencyList.prepend(s + '\t' + QString::number(long(num)));
               if(cfg.preferences.typeOfSort == 1)frequencyList.prepend(s + '\t' + QString::number(long(num)));
               if(cfg.preferences.typeOfSort == 0)
               {
                   countItemStringZero = QString::number(long(num)).rightJustified(6, '0');
                   frequencyList.prepend(countItemStringZero + s + '\t' + QString::number(long(num)));
               }
           }
           num = -num;
       }
 
   qDebug() << "Count: " << tm.elapsed();
   tm.start();
 
   // СТРОИМ СПИСОК
   if(cfg.preferences.typeOfSort != 2)qSort(frequencyList);
 
   textory.enableAdd( true );
 
   qDebug() << "Data sort: " << tm.elapsed();
   tm.start();
 
   if(cfg.preferences.typeOfSort == 0 || cfg.preferences.typeOfSort == 2)
   {
       foreach (QString itm, frequencyList)
       {
           if(cfg.preferences.typeOfSort == 0)itm.remove(0,6);
           textory.addItem( Textory::Item( 1, itm ) );
       }
   }
 
   if(cfg.preferences.typeOfSort == 1)
   {
       QListIterator<QString>itm(frequencyList);
       itm.toBack();
       while (itm.hasPrevious())
           textory.addItem( Textory::Item( 1, itm.previous() ) );
   }
 
   qDebug() << "Clear zero: " << tm.elapsed();
   tm.start();
 
   countItemFullString.setNum(countItemFull);
 
   ui.textoryPaneWidget->getTextoryLabel().setText( "Frequency list (" + countItemFullString + ")" );
 
   qDebug() << "Write name: " << tm.elapsed();
}


Название: Re: Регулярное выражение с QString
Отправлено: Spark от Август 02, 2013, 18:46
Результаты после оптимизации:
По частотности:
Reade Data:  8858
Data toLower:  310
Data split:  9582
Count:  3684
Data sort:  352
Clear zero:  332
Write name:  0

По алфавиту:
Reade Data:  8807
Data toLower:  308
Data split:  9539
Count:  2886
Data sort:  280
Clear zero:  0
Write name:  0

Без сортировки:
Reade Data:  8737
Data toLower:  311
Data split:  9491
Count:  2878
Data sort:  0
Clear zero:  11
Write name:  0

Процентов на 25 возросла скорость построения списка.

Можно, что либо еще предпринять?


Название: Re: Регулярное выражение с QString
Отправлено: kambala от Август 02, 2013, 19:36
Можно ли табуляцию увеличить на определенное число символов?
что это значит?


Название: Re: Регулярное выражение с QString
Отправлено: Spark от Август 02, 2013, 19:48
Можно ли табуляцию увеличить на определенное число символов?
что это значит?
В окне вывод у меня колонка слов и частоты через табулятор:
(s + '\t' + QString::number(long(num)))
Получается типа ровной таблицы в две колонки.
Но если слово длинное то табличка в этом месте рушится. Надо увеличить число символов для табуляции.
В принципе можно поставить две табуляции, но длинновато получится.

Возможно в конечном варианте будет настоящая табличка, но пока так.


Название: Re: Регулярное выражение с QString
Отправлено: Spark от Август 04, 2013, 04:17
Пока форум барахлил, произвел некоторую оптимизацию кода, убрал лишние промежуточные переменные и добавил фишку - Wildcard и несколькь доработал окно настроек.
Выкладываю листинги. Покритикуйте все, что можно покритиковать.
Слоты в mainwindow.cc:
Код
C++ (Qt)
void MainWindow::wordStat()
{
   QTime tm;
   tm.start();
 
   QClipboard *clipboard = QApplication::clipboard();
   QString originalText = clipboard->text();
   QString addZero;
   QStringList listFull;
   QStringList frequencyList;
 
   qDebug() << "Reade Data: " << tm.elapsed();
   tm.start();
 
   textory.clear();
   textory.enableAdd( true );
 
   // ОСТАВЛЯЕМ ТЕКСТ
   if(cfg.preferences.langStatSort == 0)listFull = originalText.toLower().split(QRegExp("[\\s\\W\\d_]+"),QString::SkipEmptyParts);
 
   // ОСТАВЛЯЕМ АНГЛИЙКИЙ
   if(cfg.preferences.langStatSort == 1)listFull = originalText.toLower().split(QRegExp("[^a-z]+"),QString::SkipEmptyParts);
 
   // ОСТАВЛЯЕМ РУССКИЙ
   if(cfg.preferences.langStatSort == 2)listFull = originalText.toLower().split(QRegExp(QString::fromUtf8("[^а-яё]+")),QString::SkipEmptyParts);
 
   qDebug() << "Data split: " << tm.elapsed();
   tm.start();
 
   // ПОСТРОЕНИЕ СПИСКА
 
   QRegExp rx(muRegExp);
   rx.setPatternSyntax(QRegExp::Wildcard);
 
   QHash<QString, int> frequencyHash;
   foreach (QString s, listFull) ++frequencyHash[s];
   frequencyList.reserve(listFull.size());
   foreach (QString s, listFull) {
       if(s.size() < cfg.preferences.minSizeWord || s.size() > cfg.preferences.maxSizeWord )continue;
       if(!muRegExp.isEmpty() && !rx.exactMatch(s))continue;
       int & num = frequencyHash[s];
       if(num < 0) continue;
       if(num >= cfg.preferences.minRepeats ) {
           if(cfg.preferences.typeOfSort == 2)frequencyList.prepend(s + '\t' + QString::number(long(num)));
           if(cfg.preferences.typeOfSort == 1)frequencyList.prepend(s + '\t' + QString::number(long(num)));
           if(cfg.preferences.typeOfSort == 0)
           {
               addZero = QString::number(long(num)).rightJustified(6, '0');
               frequencyList.prepend(addZero + s + '\t' + QString::number(long(num)));
           }
       }
       num = -num;
   }
 
   qDebug() << "Count: " << tm.elapsed();
   tm.start();
 
   if(cfg.preferences.typeOfSort != 2)qSort(frequencyList);
 
   // ВЫВОД СПИСКА
   qDebug() << "Data sort: " << tm.elapsed();
   tm.start();
 
   if(cfg.preferences.typeOfSort == 0 || cfg.preferences.typeOfSort == 2)
   {
       foreach (QString itm, frequencyList)
       {
           if(cfg.preferences.typeOfSort == 0)itm.remove(0,6);
           textory.addItem( Textory::Item( 1, itm ) );
       }
   }
 
   if(cfg.preferences.typeOfSort == 1)
   {
       QListIterator<QString>itm(frequencyList);
       itm.toBack();
       while (itm.hasPrevious())
           textory.addItem( Textory::Item( 1, itm.previous() ) );
   }
 
   qDebug() << "Out list: " << tm.elapsed();
   tm.start();
 
   ui.textoryPaneWidget->getTextoryLabel().setText( "Frequency list (" + QString::number(long(listFull.size())) + ")" );
 
   qDebug() << "Write name: " << tm.elapsed();
}
 
void MainWindow::wordStatWidget()
{
   WordStatDialog *dialog = new WordStatDialog( cfg );
   dialog->setWindowFlags(Qt::WindowStaysOnTopHint);
   connect(dialog->addFromClipboardButton, SIGNAL(clicked()), this, SLOT(wordStat()));
   connect(dialog->setWildcardLineEdit, SIGNAL(textChanged(QString)), this, SLOT(regExpChange(QString)));
   dialog->show();
}
 
void MainWindow::regExpChange(QString regExp)
{
  muRegExp = regExp;
}

Обратите внимание как произвел передачу регеспа. Честно говоря, провозился довольно долго, что бы понять как это делается (до этого обходился передачей через конфиг). Ну что поделать, не знание... не освобождает от...
Так вот достаточно ли корректно я это сделал или можно было как то попроще это сделать?

Однако, добавление плюсика в регесп
split(QRegExp("[^a-z]+")
дало 50-процентный выигрыш по времени на этой операции. И на этапе разделения, сэкономило секунд 7. Не плохо.
И теперь результаты при разделении английского, примерно таковы:
Reade Data:  8821
Data split:  7804
Count:  1228
Data sort:  0
Out list:  3
Write name:  0

По сравнению со старыми:
Английских:
Reade Data:  8906
Data toLower:  307
Data split:  15160
Count:  1523
Data sort:  92
Clear zero:  4
Write name:  0

Может еще будут предложения по достижения наивысшей скорости в рамках QT?


Название: Re: Регулярное выражение с QString
Отправлено: Spark от Август 04, 2013, 04:31
Собственно, обновленное окно настроек:
(http://s53.radikal.ru/i140/1308/17/6b84fce52cd6t.jpg) (http://radikal.ru/fp/8b99b65a7b0e4129b1356178f9ed46d6)
wordstat.hh
Код
C++ (Qt)
#ifndef WORDSTAT_HH
#define WORDSTAT_HH
 
#include <QDialog>
 
#include "config.hh"
#include "mainwindow.hh"
 
class QLabel;
class QSpinBox;
class QComboBox;
class QPushButton;
 
class WordStatDialog : public QDialog
{
   Q_OBJECT
 
public:
   WordStatDialog( Config::Class &cfg_, QWidget * parent = 0 );
 
   QPushButton *addFromClipboardButton;
 
   QLineEdit *setWildcardLineEdit;
 
private slots:
   void addFromClipboardButtonClicked();
   void setMinValue(int);
   void setMinSizeWordButtonClicked();
   void setMaxSizeWordButtonClicked();
 
private:
   Config::Class &cfg;
 
   QLabel *setMinSizeWordLabel;
   QLabel *setMaxSizeWordLabel;
   QLabel *setSizeLabel;
   QLabel *setMinRepeatsLabel;
   QLabel *setLanguageLabel;
   QLabel *setTypeOfSortLabel;
   QLabel *setWildcardLabel;
 
   QSpinBox *setMinSizeWordSpinBox;
   QSpinBox *setMaxSizeWordSpinBox;
   QSpinBox *setMinRepeatsSpinBox;
 
   QPushButton *setMinSizeWordButton;
   QPushButton *setMaxSizeWordButton;
 
   QComboBox *setLanguageComboBox;
   QComboBox *setTypeOfSortComboBox;
 
};
 
#endif // WORDSTAT_HH

wordstat.cc
Код
C++ (Qt)
#include <QtGui>
 
#include "wordstat.hh"
 
WordStatDialog::WordStatDialog( Config::Class &cfg_, QWidget *parent ) :
   QDialog( parent ),
   cfg(cfg_)
 
{
   setWindowTitle(tr("WordStat"));
   setMinimumWidth(210);
 
   setMinSizeWordLabel = new QLabel(tr("Min Of Letters:"));
   setMinSizeWordSpinBox = new QSpinBox();
   setMinSizeWordSpinBox->setValue(cfg.preferences.minSizeWord);
   setMinSizeWordSpinBox->setMinimum(1);
   setMinSizeWordSpinBox->setMaximum(99);
 
   setMaxSizeWordLabel = new QLabel(tr("Max Of Letters:"));
   setMaxSizeWordSpinBox = new QSpinBox();
   setMaxSizeWordSpinBox->setValue(cfg.preferences.maxSizeWord);
   setMaxSizeWordSpinBox->setMinimum(setMinSizeWordSpinBox->value());
   setMaxSizeWordSpinBox->setMaximum(99);
 
   connect(setMinSizeWordSpinBox, SIGNAL(valueChanged(int)),
           this, SLOT(setMinValue(int)));
 
   setMinRepeatsLabel = new QLabel(tr("Min Repeats:"));
   setMinRepeatsSpinBox = new QSpinBox();
   setMinRepeatsSpinBox->setValue(cfg.preferences.minRepeats);
   setMinRepeatsSpinBox->setMinimum(1);
   setMinRepeatsSpinBox->setMaximum(999);
 
   setLanguageLabel = new QLabel(tr("Language:"));
   setLanguageComboBox = new QComboBox();
   setLanguageComboBox->addItem("All Text");
   setLanguageComboBox->addItem("English");
   setLanguageComboBox->addItem("Russian");
   setLanguageComboBox->setCurrentIndex(cfg.preferences.langStatSort);
 
   setTypeOfSortLabel = new QLabel(tr("Type Of Sort:"));
   setTypeOfSortComboBox = new QComboBox();
   setTypeOfSortComboBox->addItem("Amount");
   setTypeOfSortComboBox->addItem("Alphabet");
   setTypeOfSortComboBox->addItem("No Sort");
   setTypeOfSortComboBox->setCurrentIndex(cfg.preferences.typeOfSort);
 
   setWildcardLabel = new QLabel(tr("Wildcard:"));
   setWildcardLineEdit = new QLineEdit();
   setWildcardLabel->setBuddy(setWildcardLineEdit);
 
   setSizeLabel = new QLabel(tr("Set Size Word:"));
   setMinSizeWordButton = new QPushButton(tr("Min Size"));
   setMaxSizeWordButton = new QPushButton(tr("Max Size"));
 
   addFromClipboardButton = new QPushButton(tr("Clipboard"));
 
   QGridLayout *wordStatLayout = new QGridLayout;
   wordStatLayout->addWidget(setMinSizeWordLabel, 0, 0);
   wordStatLayout->addWidget(setMinSizeWordSpinBox, 0, 1, 1, 2);
   wordStatLayout->addWidget(setMaxSizeWordLabel, 1, 0);
   wordStatLayout->addWidget(setMaxSizeWordSpinBox, 1, 1, 1, 2);
 
   wordStatLayout->addWidget(setSizeLabel, 2, 0);
   wordStatLayout->addWidget(setMinSizeWordButton, 2, 1);
   wordStatLayout->addWidget(setMaxSizeWordButton, 2, 2);
 
   wordStatLayout->addWidget(setMinRepeatsLabel, 3, 0);
   wordStatLayout->addWidget(setMinRepeatsSpinBox, 3, 1, 1, 2);
   wordStatLayout->addWidget(setLanguageLabel, 4, 0);
   wordStatLayout->addWidget(setLanguageComboBox, 4, 1, 1, 2);
   wordStatLayout->addWidget(setTypeOfSortLabel, 5, 0, 1, 2);
   wordStatLayout->addWidget(setTypeOfSortComboBox, 5, 1, 1, 2);
 
   wordStatLayout->addWidget(setWildcardLabel, 6, 0);
   wordStatLayout->addWidget(setWildcardLineEdit, 6, 1, 1, 2);
 
   wordStatLayout->addWidget(addFromClipboardButton, 7, 0, 1, 3);
 
   QVBoxLayout *mainWordStatLayout = new QVBoxLayout;
   mainWordStatLayout->addLayout(wordStatLayout);
   setLayout(mainWordStatLayout);
 
   connect(addFromClipboardButton, SIGNAL(clicked()),
           this, SLOT(addFromClipboardButtonClicked()));
 
   connect(setMinSizeWordButton, SIGNAL(clicked()),
           this, SLOT(setMinSizeWordButtonClicked()));
   connect(setMaxSizeWordButton, SIGNAL(clicked()),
           this, SLOT(setMaxSizeWordButtonClicked()));
}
 
void WordStatDialog::setMinValue(int)
{
   if(setMinSizeWordSpinBox->value() > setMaxSizeWordSpinBox->value())
       setMaxSizeWordSpinBox->setValue(setMinSizeWordSpinBox->value());
   setMaxSizeWordSpinBox->setMinimum(setMinSizeWordSpinBox->value());
}
 
void WordStatDialog::setMinSizeWordButtonClicked()
{
   setMaxSizeWordSpinBox->setValue(setMinSizeWordSpinBox->value());
}
 
void WordStatDialog::setMaxSizeWordButtonClicked()
{
   setMaxSizeWordSpinBox->setValue(99);
}
 
void WordStatDialog::addFromClipboardButtonClicked()
{
   if(setWildcardLineEdit->text().startsWith(" "))setWildcardLineEdit->clear();
   cfg.preferences.minSizeWord = setMinSizeWordSpinBox->value();
   cfg.preferences.maxSizeWord = setMaxSizeWordSpinBox->value();
   cfg.preferences.minRepeats = setMinRepeatsSpinBox->value();
   cfg.preferences.langStatSort = setLanguageComboBox->currentIndex();
   cfg.preferences.typeOfSort = setTypeOfSortComboBox->currentIndex();
}


Название: Re: Регулярное выражение с QString
Отправлено: Spark от Август 04, 2013, 05:48
Wildcard уже в общем то выходит за рамки стандартных настроек программ подобного класса. Возможно стоит добавить максимальное число повторений.


Название: Re: Регулярное выражение с QString
Отправлено: Igors от Август 04, 2013, 06:37
Код
C++ (Qt)
   // ОСТАВЛЯЕМ ТЕКСТ
   if(cfg.preferences.langStatSort == 0)listFull = originalText.toLower().split(QRegExp("[\\s\\W\\d_]+"),QString::SkipEmptyParts);
 
   // ОСТАВЛЯЕМ АНГЛИЙКИЙ
   if(cfg.preferences.langStatSort == 1)listFull = originalText.toLower().split(QRegExp("[^a-z]+"),QString::SkipEmptyParts);
 
   // ОСТАВЛЯЕМ РУССКИЙ
   if(cfg.preferences.langStatSort == 2)listFull = originalText.toLower().split(QRegExp(QString::fromUtf8("[^а-яё]+")),QString::SkipEmptyParts);
 
А Вас не смущает что масса текста в 3 экземплярах? ("не ленивый программист")
Код
C++ (Qt)
const QString mask[3] = {
QString("[\\s\\W\\d_]+"),
QString("[^a-z]+"),
QString::fromUtf8("[^а-яё]+"),
};
QRegExp rexp(mask[cfg.preferences.langStatSort]);
listFull = originalText.toLower().split(rexp, QString::SkipEmptyParts);
 


Название: Re: Регулярное выражение с QString
Отправлено: Spark от Август 04, 2013, 07:21
Смущает :). Но знать бы где соломку подстелить?
Спасибо.
Здесь точно 3, а не 2?
const QString mask[3]

А по поводу табуляции есть совет? http://www.prog.org.ru/index.php?topic=25332.msg181750#msg181750
Как подравнять колоночки?


Название: Re: Регулярное выражение с QString
Отправлено: Igors от Август 04, 2013, 07:30
Здесь точно 3, а не 2?
const QString mask[3]
Элементов 3 (mask[0], mask[1], mask[2]). Ну что же Вы такие пузыри пускаете  :'(

А по поводу табуляции есть совет? http://www.prog.org.ru/index.php?topic=25332.msg181750#msg181750
Как подравнять колоночки?
Сделвть таблицу (в Qt легко)


Название: Re: Регулярное выражение с QString
Отправлено: Spark от Август 04, 2013, 07:42
Сделвть таблицу (в Qt легко)
Ну это таблицу, до нее дело дойдет. А вот сейчас я зажат в рамках виджета вывода информации построчно. В принципе нормально в две колонки получается. Наглядно. Но вот слова превышающие длину табуляции, выбиваются из колеи:
(http://s018.radikal.ru/i528/1308/e7/f910248241dat.jpg) (http://radikal.ru/fp/fc10ecd0356545c882b98cadc7be9b90)
Хотелось бы просто иметь возможность отрегулировать табуляцию, как это возможно в некоторых редакторах.


Название: Re: Регулярное выражение с QString
Отправлено: Igors от Август 04, 2013, 08:16
Хотелось бы просто иметь возможность отрегулировать табуляцию, как это возможно в некоторых редакторах.
Нет смысла тратить время на ущербное/временное решение, тем более если нормальную таблицу сделать - ну минут 10, т.е. просто съесть плюшку   :)


Название: Re: Регулярное выражение с QString
Отправлено: Spark от Август 04, 2013, 09:04
Хотелось бы просто иметь возможность отрегулировать табуляцию, как это возможно в некоторых редакторах.
Нет смысла тратить время на ущербное/временное решение, тем более если нормальную таблицу сделать - ну минут 10, т.е. просто съесть плюшку   :)
Ok! I agree with you.
Я подумаю. И конечно, для меня это не будет 10 минут. Во-первых, нет опыта. Во-вторых, надо интегрировать это дело как то в готовую программу. Модули для которой я пишу.
Если бы надо было просто составить таблицу, то думаю справился бы достаточно быстро.

Но если вас не затруднит, простенький пример как вывести текущую информацию (слово - частота) в простейшую табличку в две колонки. Конечно, сам бы смог выдать очередной код, но не хочется повторять типичных ошибок.
Ну или с чего начать?


Название: Re: Регулярное выражение с QString
Отправлено: Igors от Август 04, 2013, 10:39
Но если вас не затруднит, простенький пример как вывести текущую информацию (слово - частота) в простейшую табличку в две колонки. Конечно, сам бы смог выдать очередной код, но не хочется повторять типичных ошибок.
Ну или с чего начать?
Не то чтобы затруднит, но если Вы откроете QTableView и перепишете оттудв - будет намного быстрее  :)


Название: Re: Регулярное выражение с QString
Отправлено: Spark от Август 04, 2013, 11:34
Не то чтобы затруднит, но если Вы откроете QTableView и перепишете оттудв - будет намного быстрее  :)
Все понял. Спасибо.
В ближайшем будущем попробую переделать.


Название: Re: Регулярное выражение с QString
Отправлено: Spark от Август 04, 2013, 11:38
Можно ли еще, что сделать, уменьшить код, оптимизировать, ускорить в рамках этой функции и QT?:
Код
C++ (Qt)
void MainWindow::wordStat()
{
   QTime tm;
   tm.start();
 
   QClipboard *clipboard = QApplication::clipboard();
   QString originalText = clipboard->text();
   QString addZero;
   QStringList listFull;
   QStringList frequencyList;
 
   qDebug() << "Reade Data: " << tm.elapsed();
   tm.start();
 
   textory.clear();
   textory.enableAdd( true );
 
   // ОСТАВЛЯЕМ ВЕСЬ ТЕКСТ/АНГЛИЙСКИЙ/РУССКИЙ
   const QString mask[3] = {
    QString("[\\s\\W\\d_]+"),
    QString("[^a-z]+"),
    QString::fromUtf8("[^а-яё]+"),
   };
   QRegExp rexp(mask[cfg.preferences.langStatSort]);
   listFull = originalText.toLower().split(rexp, QString::SkipEmptyParts);
 
   qDebug() << "Data split: " << tm.elapsed();
   tm.start();
 
   // ПОСТРОЕНИЕ СПИСКА
   QRegExp rx(muRegExp);
   rx.setPatternSyntax(QRegExp::Wildcard);
 
   QHash<QString, int> frequencyHash;
   foreach (QString s, listFull) ++frequencyHash[s];
   frequencyList.reserve(listFull.size());
   foreach (QString s, listFull) {
       if(s.size() < cfg.preferences.minSizeWord || s.size() > cfg.preferences.maxSizeWord )continue;
       if(!muRegExp.isEmpty() && !rx.exactMatch(s))continue;
       int & num = frequencyHash[s];
       if(num < 0) continue;
       if(num >= cfg.preferences.minRepeats ) {
           if(cfg.preferences.typeOfSort == 2)frequencyList.prepend(s + '\t' + QString::number(long(num)));
           if(cfg.preferences.typeOfSort == 1)frequencyList.prepend(s + '\t' + QString::number(long(num)));
           if(cfg.preferences.typeOfSort == 0) {
               addZero = QString::number(long(num)).rightJustified(6, '0');
               frequencyList.prepend(addZero + s + '\t' + QString::number(long(num)));
           }
       }
       num = -num;
   }
 
   qDebug() << "Count: " << tm.elapsed();
   tm.start();
 
   if(cfg.preferences.typeOfSort != 2)qSort(frequencyList);
 
   // ВЫВОД СПИСКА
   qDebug() << "Data sort: " << tm.elapsed();
   tm.start();
 
   if(cfg.preferences.typeOfSort == 0 || cfg.preferences.typeOfSort == 2) {
       foreach (QString itm, frequencyList) {
           if(cfg.preferences.typeOfSort == 0)itm.remove(0,6);
           textory.addItem( Textory::Item( 1, itm ) );
       }
   }
 
   if(cfg.preferences.typeOfSort == 1) {
       QListIterator<QString>itm(frequencyList);
       itm.toBack();
       while (itm.hasPrevious())
           textory.addItem( Textory::Item( 1, itm.previous() ) );
   }
 
   qDebug() << "Out list: " << tm.elapsed();
   tm.start();
 
   cfg.textoryName = "Frequency list (" + QString::number(long(listFull.size())) + ")";
   ui.textoryPaneWidget->getTextoryLabel().setText( cfg.textoryName );
 
   qDebug() << "Write name: " << tm.elapsed();
}


Название: Re: Регулярное выражение с QString
Отправлено: Igors от Август 04, 2013, 14:08
Код
C++ (Qt)
           if(cfg.preferences.typeOfSort == 2)frequencyList.prepend(s + '\t' + QString::number(long(num)));
           if(cfg.preferences.typeOfSort == 1)frequencyList.prepend(s + '\t' + QString::number(long(num)));
           if(cfg.preferences.typeOfSort == 0) {
}
Если с пробелами не наведете порядок - больше не отвечу  :) Здесь лучше так
Код
C++ (Qt)
// в начале
const MyPref & pref = cfg.preferences;   // MyPref = тот тип что cfg.preferences
enum {
sort_None = 0,
sort_Freq = 1,
sort_Crazy = 2,   // даете имена по смыслу, этл для примера
};
...
if  (pref.typeOfSort != sort_None)
frequencyList.prepend(s + '\t' + QString::number(long(num)));
else {
...
 
Ну и научитесь нормально сортировку делать, это несложно



Название: Re: Регулярное выражение с QString
Отправлено: Spark от Август 04, 2013, 16:13
Если с пробелами не наведете порядок - больше не отвечу  :) Здесь лучше так
Набрался с чужого кода. Если не вы, то ктож меня теперь научит правилам хорошего кода :).
Не ясно для чего это?:
Код
C++ (Qt)
enum {
sort_None = 0,
sort_Freq = 1,
sort_Crazy = 2,   // даете имена по смыслу, этл для примера
};
Компактнее не становится. Только для того, кто после меня будет ковырять код? Просто ноль вставил.
Подровнял:
Код
C++ (Qt)
void MainWindow::wordStat()
{
   QTime tm;
   tm.start();
 
   const Config::Preferences & pref = cfg.preferences;
   QClipboard *clipboard = QApplication::clipboard();
   QString originalText = clipboard->text();
   QString addZero;
   QStringList listFull;
   QStringList frequencyList;
 
   qDebug() << "Reade Data: " << tm.elapsed();
   tm.start();
 
   textory.clear();
   textory.enableAdd( true );
 
   // ОСТАВЛЯЕМ ВЕСЬ ТЕКСТ/АНГЛИЙСКИЙ/РУССКИЙ
   const QString mask[3] = {
       QString("[\\s\\W\\d_]+"),
       QString("[^a-z]+"),
       QString::fromUtf8("[^а-яё]+"),
   };
   QRegExp rexp(mask[pref.langStatSort]);
   listFull = originalText.toLower().split(rexp, QString::SkipEmptyParts);
 
   qDebug() << "Data split: " << tm.elapsed();
   tm.start();
 
   // ПОСТРОЕНИЕ СПИСКА
   QRegExp rx(muRegExp);
   rx.setPatternSyntax(QRegExp::Wildcard);
 
   QHash<QString, int> frequencyHash;
   foreach (QString s, listFull) ++frequencyHash[s];
   frequencyList.reserve(listFull.size());
   foreach (QString s, listFull) {
       if (s.size() < pref.minSizeWord || s.size() > pref.maxSizeWord )continue;
       if (!muRegExp.isEmpty() && !rx.exactMatch(s))continue;
       int & num = frequencyHash[s];
       if (num < 0) continue;
       if (num >= pref.minRepeats ) {
           if  (pref.typeOfSort != 0)
               frequencyList.prepend(s + '\t' + QString::number(long(num)));
           else {
               addZero = QString::number(long(num)).rightJustified(6, '0');
               frequencyList.prepend(addZero + s + '\t' + QString::number(long(num)));
           }
       }
       num = -num;
   }
 
   qDebug() << "Count: " << tm.elapsed();
   tm.start();
 
   if (pref.typeOfSort != 2)qSort(frequencyList);
 
   // ВЫВОД СПИСКА
   qDebug() << "Data sort: " << tm.elapsed();
   tm.start();
 
   if (pref.typeOfSort == 0 || pref.typeOfSort == 2) {
       foreach (QString itm, frequencyList) {
           if(pref.typeOfSort == 0)itm.remove(0,6);
           textory.addItem( Textory::Item( 1, itm ) );
       }
   }
 
   if (pref.typeOfSort == 1) {
       QListIterator<QString>itm(frequencyList);
       itm.toBack();
       while (itm.hasPrevious())
           textory.addItem( Textory::Item( 1, itm.previous() ) );
   }
 
   qDebug() << "Out list: " << tm.elapsed();
   tm.start();
 
   cfg.textoryName = "Frequency list (" + QString::number(long(listFull.size())) + ")";
   ui.textoryPaneWidget->getTextoryLabel().setText( cfg.textoryName );
 
   qDebug() << "Write name: " << tm.elapsed();
}

Ну и научитесь нормально сортировку делать, это несложно
Поясните для меня непутевого, что имеете ввиду? Сразу постараюсь учесть.


Название: Re: Регулярное выражение с QString
Отправлено: Spark от Август 04, 2013, 16:19
Устал на самом деле (да и ночь у нас уже), но попутно накропал дополнительную функцию. Немного нового и поверхностно ознакомился и честно признаюсь, что на половину делал опираясь на полученные знания, а наполовину методом тыка:
Код
C++ (Qt)
void MainWindow::textoryInBuffer()
{
   QStringList textoryStrings;
 
   QString line;
   QList< Textory::Item > const & items = textory.getItems();
 
   QList< Textory::Item >::const_iterator i;
   for ( i = items.constBegin(); i != items.constEnd(); ++i ){
       line = i->word.toUtf8();
       textoryStrings.append(line);
   }
   QApplication::clipboard()->setText( textoryStrings.join( QString::fromLatin1( "\n" ) ) );
}
Работает, но технически все ли правильно?


Название: Re: Регулярное выражение с QString
Отправлено: Spark от Август 04, 2013, 16:22
И по поводу стиля. Опираюсь я действительно на чужой код и соответственно стилистика заимствована. Где еще у меня не красиво?


Название: Re: Регулярное выражение с QString
Отправлено: Majestio от Август 04, 2013, 16:31
Не то чтобы затруднит, но если Вы откроете QTableView и перепишете оттудв - будет намного быстрее  :)
Все понял. Спасибо.
В ближайшем будущем попробую переделать.

В этом (http://www.prog.org.ru/index.php?topic=25332.msg181312#msg181312) посте, в прикрепленном архиве я набрасывал примерчик - там все это работает с таблицей. Можете не долго думая взять за основу и не мучаться с табуляциями. За одно мимоходом ознакомитесь с концепцией модель-представление - пригодиться в будущем.


Название: Re: Регулярное выражение с QString
Отправлено: Spark от Август 04, 2013, 16:32
Все до кучи накропал. Работает. Завтра буду разбирать ошибки.
Код
C++ (Qt)
void MainWindow::textoryFromBuffer()
{
   QClipboard *clipboard = QApplication::clipboard();
   QString originalBuffer = clipboard->text();
   QTextStream bufferStream( & originalBuffer );
   QString itemBufStr, itemTextStr;
   QStringList textList;
 
   textory.clear();
 
   do
   {
       itemBufStr = bufferStream.readLine();
 
       itemTextStr = itemBufStr.trimmed();
       if ( itemTextStr.isEmpty() )
           continue;
 
       textList.prepend( itemTextStr );
   } while ( !bufferStream.atEnd() );
 
   textory.enableAdd( true );
 
   foreach (QString itm, textList)
       textory.addItem( Textory::Item( 1, itm ) );
 
   cfg.textoryName = "From Buffer";
   ui.textoryPaneWidget->getTextoryLabel().setText( cfg.textoryName );
}


Название: Re: Регулярное выражение с QString
Отправлено: Spark от Август 04, 2013, 16:41
...посте, в прикрепленном архиве я набрасывал примерчик - там все это работает с таблицей. Можете не долго думая взять за основу и не мучаться с табуляциями. За одно мимоходом ознакомитесь с концепцией модель-представление - пригодиться в будущем.
Спасибо. Попробую разобрать пример и использовать. Хотел я отложить в ящик, вроде и так все не плохо работает, но видимо придется заняться оформлением вывода. Тем более предполагается более крутая обработка текста.


Название: Re: Регулярное выражение с QString
Отправлено: Igors от Август 05, 2013, 06:10
Код
C++ (Qt)
enum {
sort_None = 0,
sort_Freq = 1,
sort_Crazy = 2,   // даете имена по смыслу, этл для примера
};
Компактнее не становится. Только для того, кто после меня будет ковырять код? Просто ноль вставил.
Выполняйте, и для typeOffset тоже. Свое мнение будете высказывать когда освоите что говорят  :)


Название: Re: Регулярное выражение с QString
Отправлено: Spark от Август 05, 2013, 11:17
Выполняйте, и для typeOffset тоже. Свое мнение будете высказывать когда освоите что говорят  :)
Выполнить не проблема. Но было бы интересно знать преимущества. Пока только код стал длиннее. Разве, что читабельней? Опять правила хорошего кода?
Ok! Заодно добавил немного статистики - ПРОЦЕНТ ОСТАВЛЕННЫХ СЛОВ ОТ КОЛИЧЕСТВА ОРИГИНАЛЬНЫХ:
Код
C++ (Qt)
void MainWindow::wordStat()
{
   QTime tm;
   tm.start();
 
   const Config::Preferences & pref = cfg.preferences;
   QClipboard *clipboard = QApplication::clipboard();
   QString originalText = clipboard->text();
   QString addZero;
   QStringList listFull;
   QStringList frequencyList;
 
   qDebug() << "Reade Data: " << tm.elapsed();
   tm.start();
 
   textory.clear();
   textory.enableAdd( true );
 
   // ОСТАВЛЯЕМ: ВЕСЬ ТЕКСТ/АНГЛИЙСКИЙ/РУССКИЙ
   const QString mask[3] = {
       QString("[\\s\\W\\d_]+"),
       QString("[^a-z]+"),
       QString::fromUtf8("[^а-яё]+"),
   };
   QRegExp rexp(mask[pref.langStatSort]);
   listFull = originalText.toLower().split(rexp, QString::SkipEmptyParts);
 
   qDebug() << "Data split: " << tm.elapsed();
   tm.start();
 
   // ПОСТРОЕНИЕ СПИСКА
   QRegExp rx(muRegExp);
   rx.setPatternSyntax(QRegExp::Wildcard);
   enum {
       sort_Amount = 0,
       sort_Alphabet = 1,
       sort_None = 2
   };
 
   QHash<QString, int> freqHash;
   foreach (QString s, listFull) ++freqHash[s];
 
   frequencyList.reserve(listFull.size());
   foreach (QString s, listFull) {
       if (s.size() < pref.minSizeWord || s.size() > pref.maxSizeWord )continue;
       if (!muRegExp.isEmpty() && !rx.exactMatch(s))continue;
       int & num = freqHash[s];
       if (num < 0) continue;
       if (num >= pref.minRepeats ) {
           if  (pref.typeOfSort != sort_Amount)
               frequencyList.prepend(s + '\t' + QString::number(long(num)));
           else {
               addZero = QString::number(long(num)).rightJustified(6, '0');
               frequencyList.prepend(addZero + s + '\t' + QString::number(long(num)));
           }
       }
       num = -num;
   }
 
   qDebug() << "Count: " << tm.elapsed();
   tm.start();
 
   if (pref.typeOfSort != sort_None)qSort(frequencyList);
 
   // ВЫВОД СПИСКА
   qDebug() << "Data sort: " << tm.elapsed();
   tm.start();
 
   if (pref.typeOfSort == sort_Amount || pref.typeOfSort == sort_None) {
       foreach (QString itm, frequencyList) {
           if(pref.typeOfSort == 0)itm.remove(0,6);
           textory.addItem( Textory::Item( 1, itm ) );
       }
   }
 
   if (pref.typeOfSort == sort_Alphabet) {
       QListIterator<QString>itm(frequencyList);
       itm.toBack();
       while (itm.hasPrevious())
           textory.addItem( Textory::Item( 1, itm.previous() ) );
   }
 
   qDebug() << "Out list: " << tm.elapsed();
   tm.start();
 
   // ПРОЦЕНТ ОСТАВЛЕННЫХ СЛОВ ОТ КОЛИЧЕСТВА ОРИГИНАЛЬНЫХ
   double full(freqHash.size());
   double real(textory.size());
 
   QString freqStat = "/" + QString::number(long(freqHash.size())) + "/" + QString::number(double(real * 100 / full), 'f', 2).remove(QRegExp("\\.00")) + "%";
 
   cfg.textoryName = "Frequency list (" + QString::number(long(listFull.size())) + freqStat + ")";
   ui.textoryPaneWidget->getTextoryLabel().setText( cfg.textoryName );
 
   qDebug() << "Write name: " << tm.elapsed();
}


Название: Re: Регулярное выражение с QString
Отправлено: Igors от Август 05, 2013, 12:30
Код
C++ (Qt)
   enum {
       sort_Amount = 0,
       sort_Alphabet = 1,
       sort_None = 2
   };
 
Это выносится в начало cpp файла, или h файла если это класс. None обычно соответствует нулю. Имена подбираются более тщательно, напр sort_Amount - слишком общее, лучше напр sort_ByCount

Вместо этого
Код
C++ (Qt)
   if (pref.typeOfSort == sort_Amount || pref.typeOfSort == sort_None) {
       foreach (QString itm, frequencyList) {
           if(pref.typeOfSort == 0)itm.remove(0,6);
           textory.addItem( Textory::Item( 1, itm ) );
       }
   }
 
   if (pref.typeOfSort == sort_Alphabet) {
       QListIterator<QString>itm(frequencyList);
       itm.toBack();
       while (itm.hasPrevious())
           textory.addItem( Textory::Item( 1, itm.previous() ) );
   }
 

Лучше так
Код
C++ (Qt)
QStringList & lst = frequencyList;
const int ilimit = lst.size();
for (int i = 0; i < limit; ++i) {
   switch (pref.typeOfSort) {
     case sort_None:
       textory.addItem(Textory::Item(1, lst[i]);
       break;
 
     case sort_Amount:
       textory.addItem(Textory::Item(1, lst[i].remove(0, 6)));
       breakl;  
 
     case sort_Alphabet:
       textory.addItem(Textory::Item(1, lst[limit - 1 - i]);
       break;
  }
}
 
Цель - не написать "как можно короче" (это обычно само получается), а разложить все на свои места. А то появится еще режим - и опять месить if'ы. В общем, к культуре надо приучаться  :)


Название: Re: Регулярное выражение с QString
Отправлено: Spark от Август 05, 2013, 16:57
Хорошо, лишь бы не было медленней. Как раз наклевывается новый режим.
Поправил:
Код
C++ (Qt)
void MainWindow::wordStat()
{
   QTime tm;
   tm.start();
 
   const Config::Preferences & pref = cfg.preferences;
   QClipboard *clipboard = QApplication::clipboard();
   QString originalText = clipboard->text();
   QString addZero;
   QStringList listFull;
   QStringList frequencyList;
 
   qDebug() << "Reade Data: " << tm.elapsed();
   tm.start();
 
   textory.clear();
   textory.enableAdd( true );
 
   // ОСТАВЛЯЕМ: ВЕСЬ ТЕКСТ/АНГЛИЙСКИЙ/РУССКИЙ
   const QString mask[3] = {
       QString("[\\s\\W\\d_]+"),
       QString("[^a-z]+"),
       QString::fromUtf8("[^а-яё]+"),
   };
   QRegExp rexp(mask[pref.langStatSort]);
   listFull = originalText.toLower().split(rexp, QString::SkipEmptyParts);
 
   qDebug() << "Data split: " << tm.elapsed();
   tm.start();
 
   // ПОСТРОЕНИЕ СПИСКА
   QRegExp rx(muRegExp);
   rx.setPatternSyntax(QRegExp::Wildcard);
   enum {
       sort_Amount = 0,
       sort_Alphabet = 1,
       sort_None = 2
   };
 
   QHash<QString, int> freqHash;
   foreach (QString s, listFull) ++freqHash[s];
 
   frequencyList.reserve(listFull.size());
   foreach (QString s, listFull) {
       if (s.size() < pref.minSizeWord || s.size() > pref.maxSizeWord )continue;
       if (!muRegExp.isEmpty() && !rx.exactMatch(s))continue;
       int & num = freqHash[s];
       if (num < 0) continue;
       if (num >= pref.minRepeats && num <= pref.maxRepeats) {
           if  (pref.typeOfSort != sort_Amount)
               frequencyList.prepend(s + '\t' + QString::number(long(num)));
           else {
               addZero = QString::number(long(num)).rightJustified(6, '0');
               frequencyList.prepend(addZero + s + '\t' + QString::number(long(num)));
           }
       }
       num = -num;
   }
 
   qDebug() << "Count: " << tm.elapsed();
   tm.start();
 
   if (pref.typeOfSort != sort_None)qSort(frequencyList);
 
   // ВЫВОД СПИСКА
   qDebug() << "Data sort: " << tm.elapsed();
   tm.start();
 
 
   QStringList & lst = frequencyList;
   const int ilimit = lst.size();
   for (int i = 0; i < ilimit; ++i) {
       switch (pref.typeOfSort) {
         case sort_None:
           textory.addItem(Textory::Item(1, lst[i]));
           break;
 
         case sort_Amount:
           textory.addItem(Textory::Item(1, lst[i].remove(0, 6)));
           break;
 
         case sort_Alphabet:
           textory.addItem(Textory::Item(1, lst[ilimit - 1 - i]));
           break;
      }
   }
 
   qDebug() << "Out list: " << tm.elapsed();
   tm.start();
 
   // ПРОЦЕНТ ОСТАВЛЕННЫХ СЛОВ ОТ КОЛИЧЕСТВА ОРИГИНАЛЬНЫХ
   double full(freqHash.size());
   double real(textory.size());
 
   QString freqStat = "/" + QString::number(long(freqHash.size())) + "/" + QString::number(double(real * 100 / full), 'f', 2).remove(QRegExp("\\.00")) + "%";
 
   cfg.textoryName += " (" + QString::number(long(listFull.size())) + freqStat + ")";
   ui.textoryPaneWidget->getTextoryLabel().setText( cfg.textoryName );
 
   qDebug() << "Write name: " << tm.elapsed();
}
По сути я пользуюсь стандартной булевой алгеброй. Остальные приемы только только постигаю. Так приучите меня к вещам, которые я никогда не применял :).
Спасибо!


Название: Re: Регулярное выражение с QString
Отправлено: Spark от Август 05, 2013, 17:07
Однако кое, что добавил:
(http://i080.radikal.ru/1308/61/34022ffc23fdt.jpg) (http://radikal.ru/fp/a4bae147770d4aa7aeeb8176d7e76b14)


Название: Re: Регулярное выражение с QString
Отправлено: Spark от Август 05, 2013, 20:26
Подобного рода текст:
Цитировать
Слово1
  слово
  слово

слово2
слово3
  слово

слово4
  ...
Надо собрать слова без пробела или табуляции в начале новой строки. Как организовать сплит? Пытаюсь через регесп, что бы использовать в коде:
Код
C++ (Qt)
   // ОСТАВЛЯЕМ: ВЕСЬ ТЕКСТ/АНГЛИЙСКИЙ/РУССКИЙ
   const QString mask[3] = {
       QString("[\\s\\W\\d_]+"),
       QString("[^a-z]+"),
       QString::fromUtf8("[^а-яё]+"),
   };
Не получается.
Конечно можно предварительно через те же регеспы удалить ненужные строки. Но хотелось бы сделать более оптимально, без промежуточных операций.


Название: Re: Регулярное выражение с QString
Отправлено: Spark от Август 06, 2013, 04:03
Так пока сделал:
Код
C++ (Qt)
   const QString mask[4] = {
...
       QString("\n[\\t].*\n[^\\t]"),
   };
   QRegExp rexp(mask[pref.langStatSort]);
   rexp.setMinimal(true);
   listFull = originalText.toLower().split(rexp, QString::SkipEmptyParts);
Работает, но вроде не все верно. Вроде как не учтен конец страницы. Если его захватить, то к пунктам списка добавляется пустая строка сверху и снизу:
Цитировать
Слово1


слово2


слово3
   
Ладно, прибежим с работы, разберемся.


Название: Re: Регулярное выражение с QString
Отправлено: Spark от Август 07, 2013, 14:54
Намаялся со сплиттером (для спец текста) с помощью регурярок. Не получилось. А жаль. Сделал предварительную зачистку. Тут то-же не так гладко как хотелось бы. Затруднение не в том, что бы очистить, а в том, что бы после этого подсчитать статистические результаты. Пришлось несколько разделить процесс.
В общем так пока. Работает не хуже чем остальные режимы, даже быстрее, но как то не очень красиво. Покритикуйте:
Код
C++ (Qt)
void MainWindow::wordStat()
{
   QTime tm;
   tm.start();
 
   const Config::Preferences & pref = cfg.preferences;
   QClipboard *clipboard = QApplication::clipboard();
   QString originalText = clipboard->text();
   QString addZero;
   QStringList listFull;
   QStringList frequencyList;
   int xlsCountFull(0);
 
   qDebug() << "Reade Data: " << tm.elapsed();
   tm.start();
 
   textory.clear();
   textory.enableAdd( true );
 
   // ОСТАВЛЯЕМ: ВЕСЬ ТЕКСТ/АНГЛИЙСКИЙ/РУССКИЙ
   const QString mask[4] = {
       QString("[\\s\\W\\d_]+"),
       QString("[^a-z]+"),
       QString::fromUtf8("[^а-яё]+"),
       QString("\n"),
   };
   QRegExp rexp(mask[pref.langStatSort]);
   rexp.setMinimal(true);
   listFull = originalText.toLower().split(rexp, QString::SkipEmptyParts);
 
   qDebug() << "Data split: " << tm.elapsed();
   tm.start();
 
   // ПОСТРОЕНИЕ СПИСКА
   QRegExp rx(muRegExp);
   rx.setPatternSyntax(QRegExp::Wildcard);
   enum {
       sort_Amount = 0,
       sort_Alphabet = 1,
       sort_None = 2
   };
 
   QHash<QString, int> freqHash;
   foreach (QString s, listFull) {
       if (pref.langStatSort == 3 && (s.startsWith("\t") || s.startsWith(" ") || s.startsWith("#") || s.startsWith("{{")))continue;
       ++freqHash[s];
   }
 
   frequencyList.reserve(listFull.size());
   foreach (QString s, listFull) {
 
       if (pref.langStatSort == 3 && (s.startsWith("\t") || s.startsWith(" ") || s.startsWith("#") || s.startsWith("{{")))continue;
 
       ++xlsCountFull;
 
       if (s.size() < pref.minSizeWord || s.size() > pref.maxSizeWord )continue;
       if (!muRegExp.isEmpty() && !rx.exactMatch(s))continue;
       int & num = freqHash[s];
//        if (num < 0) continue;
 
       if (num >= pref.minRepeats && num <= pref.maxRepeats) {
           if  (pref.typeOfSort != sort_Amount)
               frequencyList.prepend(s + '\t' + QString::number(long(num)));
           else {
               addZero = QString::number(long(num)).rightJustified(6, '0');
               frequencyList.prepend(addZero + s + '\t' + QString::number(long(num)));
           }
       }
//        num = -num;
   }
 
   qDebug() << "Count: " << tm.elapsed();
   tm.start();
 
   if (pref.typeOfSort != sort_None)qSort(frequencyList);
 
   // ВЫВОД СПИСКА
   qDebug() << "Data sort: " << tm.elapsed();
   tm.start();
 
   QStringList & lst = frequencyList;
   const int ilimit = lst.size();
   for (int i = 0; i < ilimit; ++i) {
       switch (pref.typeOfSort) {
       case sort_None:
           textory.addItem(Textory::Item(1, lst[i]));
           break;
 
       case sort_Amount:
           textory.addItem(Textory::Item(1, lst[i].remove(0, 6)));
           break;
 
       case sort_Alphabet:
           textory.addItem(Textory::Item(1, lst[ilimit - 1 - i]));
           break;
       }
   }
 
   qDebug() << "Out list: " << tm.elapsed();
   tm.start();
 
   // ПРОЦЕНТ ОСТАВЛЕННЫХ СЛОВ ОТ КОЛИЧЕСТВА ОРИГИНАЛЬНЫХ
   double realSort(textory.size());
   double sortWithDoubles (xlsCountFull);
   double sortNoDoubles (freqHash.size());
 
   QString freqStat = "/" + QString::number(long(sortNoDoubles)) + "/" + QString::number(double(realSort * 100 / sortNoDoubles), 'f', 2).remove(QRegExp("\\.00")) + "%";
 
   cfg.textoryName += " (" + QString::number(long(sortWithDoubles)) + freqStat + ")";
   ui.textoryPaneWidget->getTextoryLabel().setText( cfg.textoryName );
 
   qDebug() << "Write name: " << tm.elapsed();
}

Не совсем ясно для чего это (может отпала необходимость):
        if (num < 0) continue;
        ...
        num = -num;
Пока закомментировал.


Название: Re: Регулярное выражение с QString
Отправлено: Spark от Август 07, 2013, 15:09
Ясно. Раскомментировал :).


Название: Re: Регулярное выражение с QString
Отправлено: Igors от Август 07, 2013, 16:18
Покритикуйте:
Код
C++ (Qt)
   rx.setPatternSyntax(QRegExp::Wildcard);
   enum {
       sort_Amount = 0,
       sort_Alphabet = 1,
       sort_None = 2
   };
 
   QHash<QString, int> freqHash;
   foreach (QString s, listFull) {
       if (pref.langStatSort == 3 && (s.startsWith("\t") || s.startsWith(" ") || s.startsWith("#") || s.startsWith("
Позиция один: научитесь использовать константы и enum'ы. Вбивать числа/строки прямо в код метода = западло. Чего Вы лепите тройку если завели enum? Был разговор выносить enum в начало файла, имена подобрать со вкусом. Вот сделаете с любовью (а не так чтоб отвязаться) - тогда поговорим дальше. А пока свободен  :)


Название: Re: Регулярное выражение с QString
Отправлено: Spark от Август 09, 2013, 17:17
Пытаюсь вместо буфера подставить текстовый файл:
Код
C++ (Qt)
   QFile file( texFilename );
   if ( file.open( QFile::ReadOnly | QIODevice::Text ) )
   {
       QByteArray text = file.readAll();
       Qstring originalText = text;
...
Если текст в utf8 то все  в порядке. В utf16 не читает. Соответственно ясно, что надо как то установить кодек.
Пока пытаюсь разобраться самостоятельно, может кто подскажет как поступить?


Название: Re: Регулярное выражение с QString
Отправлено: kambala от Август 09, 2013, 21:22
QString::fromUtf16()


Название: Re: Регулярное выражение с QString
Отправлено: m_ax от Август 09, 2013, 23:42
QString::fromUtf16()

Эх, kambala, здесь ИМХО, проблема гораздо глубже.. Все эти fromUtf16/8 и т.д. всего лишь частности.. в которых Spark копается уже больше месяца(..

Здесь изначально проблема в самой архитектуре.. Вот представьте, ему понадобится выводить статистику не слов, а, скажем фраз. И что? Всё, что он тут написал развалится тут же... А если в будущем возникнет необходимость для пользователя "на лету" конструировать правила для выцепления каких то лексем и т.д.. Зациклившись на сплите такие задачи кажутся безнадёжными.. Но это всего лишь следствие( Причина в том, что Sark пренебрегая реально дельными советами, закапывается в совершенно не существенные на данном этапе детали..

2Spark Вот дельный совет, который для вас был уже озвучен не однократно: Перед тем как браться за реальный проект, нужно сесть, успокоиться, возможно, посмотреть в окно, взять листок бумаги и ручку и набросать примерный план того, что и как должно справляться с поставленной задачей: какие основные сущности следует ввести, что должна делать конкретная сущность и какие взаимосвязи между ними должны быть.. Этот процесс не быстрый, возможно он займёт не один день.. и всё же.. После этого более детально определяется интерфейс каждой сущьности с расчётом возможных потенциальных расширений в будущем. Здесь, пожалуй, самый ответственный момент, которому нужно уделить большее внимание. И это один из самых ответственных моментов в разработке архитектуры, который может занять большую часть времени.

И вот когда уже придёт осознание и понимание этих двух предшествующих шагов, выбирается соответствующий инструментарий.
И только после этого можно чего то там пытаться программировать.. То, что вы сейчас делаете - это как в поговорке: "бешеной собаке - семь вёрст не круг".. И особенно очень печально, что вы этого не понимаете(

          


Название: Re: Регулярное выражение с QString
Отправлено: Spark от Август 10, 2013, 04:47
m_ax Сам так делать не буду и другим изучающим не советую.
Во первых, я достаточно ясно представляю, что мне надо.
Во вторых (не люблю аналогии, поскольку их коверкают), если вам необходимо построить дом и в вашем распоряжении весь арсенал инструментов, но пользоваться вы можете только молотком, то сколько бы вы в окно не смотрели и не представляли как должен выглядеть новый дом, легче от этого не станет. Легче станет только при строительстве второго дома и тем более третьего...
В третьих, советы я слушаю и по мере осознания как они работают и их преимуществ, применяю (можно было все таки это заметить).

Но вы точно подметили на счет перспектив моего модуля и, что я собираюсь делать :). Пока проблем не вижу. Да возможно придется переделывать, но я уже умею пользоваться не только молотком :), но все таки не достаточно, что бы расслабиться, заглянуть в окно и идеи реализации шли бы как из рога изобилия. Пока, что только хотелки могут разрастись, но я их итак знаю. В общем самый действенный способ в моей ситуации - делать, ошибаться, спрашивать, исправлять, набираться опыта...


Название: Re: Регулярное выражение с QString
Отправлено: Spark от Август 10, 2013, 06:34
QString::fromUtf16()
На самом деле это первое с чего начал решать этот вопрос. К сожалению не разобрался.
Так работает:
Код
C++ (Qt)
   QFile file( textFilename );
   if ( file.open( QFile::ReadOnly | QIODevice::Text ) )
   {
       QByteArray a = file.readAll();
       QString originalText(QString::fromUtf8(a));
 
   qDebug() << "Reade Data: " << tm.elapsed();
   tm.start();
 
   textory.clear();
   textory.enableAdd( true );
 
   // ОСТАВЛЯЕМ: ВЕСЬ ТЕКСТ/АНГЛИЙСКИЙ/РУССКИЙ
   const QString mask[4] = {
       QString("[\\s\\W\\d_]+"),
       QString("[^a-z]+"),
       QString::fromUtf8("[^а-яё]+"),
       QString("\n"),
   };
   QRegExp rexp(mask[pref.langStatSort]);
   rexp.setMinimal(true);
   listFull = originalText.toLower().split(rexp, QString::SkipEmptyParts);
 
   file.close();
   }

Решение в лоб уже не работает:
Код
C++ (Qt)
       QByteArray a = file.readAll();
       QString originalText(QString::fromUtf16(a));
Здесь уже на этапе компиляции ругается.
Понимаю, что то не так с записью. Но не знаю - что.


Название: Re: Регулярное выражение с QString
Отправлено: Spark от Август 10, 2013, 06:48
Это работает, но опять же с текстом UTF-8:
Код
C++ (Qt)
       QByteArray a = file.readAll();
       QTextCodec *codec = QTextCodec::codecForName("UTF-8");
       QString originalText = codec->toUnicode(a);
Этот код уже отказывается правильно работать:
Код
C++ (Qt)
       QByteArray a = file.readAll();
       QTextCodec *codec = QTextCodec::codecForName("UTF-16");
       QString originalText = codec->toUnicode(a);
Правда в этот раз компилятор не ругается. Но программа выдает китайские иероглифы, либо вообще ничего не дает. Но можно предположить, чего ей не хватает.
На самом деле, даже если бы, что и вышло с этими двумя вариантами, то полагаю они не универсальны.


Название: Re: Регулярное выражение с QString
Отправлено: Spark от Август 10, 2013, 07:39
Желаемый результат удалось получить следующим образом и в этом случае без разницы какой текст на входе:
Код
C++ (Qt)
   QFile file( textFilename );
   if ( file.open( QFile::ReadOnly | QIODevice::Text ) )
   {      
       // РАБОТАЕТ
       QTextStream stream(&file);
       stream.setCodec("UTF-8");
       QString originalText(stream.readAll());
       stream.flush();
       file.close();
 
       textory.clear();
       textory.enableAdd( true );
 
       // ОСТАВЛЯЕМ: ВЕСЬ ТЕКСТ/АНГЛИЙСКИЙ/РУССКИЙ
       const QString mask[4] = {
           QString("[\\s\\W\\d_]+"),
           QString("[^a-z]+"),
           QString::fromUtf8("[^а-яё]+"),
           QString("\n"),
       };
       QRegExp rexp(mask[pref.langStatSort]);
       rexp.setMinimal(true);
       listFull = originalText.toLower().split(rexp, QString::SkipEmptyParts);
   }

Попутный вопрос. Есть принципиальное значение где закрывать файл (file.close())?
Может следует так:
Код
C++ (Qt)
   QFile file( textFilename );
   if ( file.open( QFile::ReadOnly | QIODevice::Text ) )
   {      
       // РАБОТАЕТ
       QTextStream stream(&file);
       stream.setCodec("UTF-8");
       QString originalText(stream.readAll());
 
       textory.clear();
       textory.enableAdd( true );
 
       // ОСТАВЛЯЕМ: ВЕСЬ ТЕКСТ/АНГЛИЙСКИЙ/РУССКИЙ
       const QString mask[4] = {
           QString("[\\s\\W\\d_]+"),
           QString("[^a-z]+"),
           QString::fromUtf8("[^а-яё]+"),
           QString("\n"),
       };
       QRegExp rexp(mask[pref.langStatSort]);
       rexp.setMinimal(true);
       listFull = originalText.toLower().split(rexp, QString::SkipEmptyParts);
 
       stream.flush();
       file.close();
   }


Название: Re: Регулярное выражение с QString
Отправлено: Spark от Август 10, 2013, 07:47
Эх, kambala, здесь ИМХО, проблема гораздо глубже.. Все эти fromUtf16/8 и т.д. всего лишь частности.. в которых Spark копается уже больше месяца(..
За эти больше месяца сделано и работают на публику(пока, что узкий круг знакомых) три модуля, аналогов которым нет. Не так уж и плохо для новичка. Это не хвастовство, это констатация фактов.
Не без помощи профи. И за помощь огромнейшее спасибо!


Название: Re: Регулярное выражение с QString
Отправлено: m_ax от Август 10, 2013, 10:33
Но вы точно подметили на счет перспектив моего модуля и, что я собираюсь делать :). Пока проблем не вижу.

Не видите? Сейчас увидите)
Что вы будете делать, если мне нужно посчитать сколько раз в тексте встречается выражение, скажем: Hello word! ?
Или я, например, хочу найти в тексте опечатки связанные с повторным написанием одного и того же слова (например the the) и т.д.
Или я хочу посчитать сколько раз в тексте встречается буква "a", сколько "b" и т.д.
Или..

Уже изначальное использование split'а для задач, которые вы пытаетесь решить - плохое решение. Ощущение, что это просто первое, что попалось вам под руку и вы этим тут же взялись строить дом..

Кстатии, по поводу дома:
Цитировать
Во вторых (не люблю аналогии, поскольку их коверкают), если вам необходимо построить дом и в вашем распоряжении весь арсенал инструментов, но пользоваться вы можете только молотком, то сколько бы вы в окно не смотрели и не представляли как должен выглядеть новый дом, легче от этого не станет.
Если "разумный" человек, берётся за постройку целого дома, более-менее представляя как пользоваться только молотком, то у меня вопрос о его разумности стоит под большим сомнением) Потому что в конечном счёте это выйдет ему гораздо дороже, как если бы он просто купил новый дом)

Я понимаю, что опыт тоже очень важен и на одной теории так просто далеко не уедешь. Но чтоб этот опыт приносил пользу нужно всё же параллельно и инструмент изучать и хвататься не за дом сразу, а скажем за табуретку, ну или за маленький домик для собаки)
   


Название: Re: Регулярное выражение с QString
Отправлено: Spark от Август 10, 2013, 11:46
Учеников можно критиковать, значит и программистов будем критиковать :).
Не видите? Сейчас увидите)
Что вы будете делать, если мне нужно посчитать сколько раз в тексте встречается выражение, скажем: Hello word! ?
Или я, например, хочу найти в тексте опечатки связанные с повторным написанием одного и того же слова (например the the) и т.д.
Или я хочу посчитать сколько раз в тексте встречается буква "a", сколько "b" и т.д.
Или..
Слишком простые задачки и на гора можно выдать их долго не думая. Но заниматься я этим не буду. Это просто никого не будет интересовать. Задача несколько серьезнее и более сложная. К тому же она, фактически, реализована :). Об этом как нибудь в другой раз.
Уже изначальное использование split'а для задач, которые вы пытаетесь решить - плохое решение. Ощущение, что это просто первое, что попалось вам под руку и вы этим тут же взялись строить дом..
Это весьма обдуманный шаг. Другое дело, что опыта нет. Ну что-ж когда то надо начинать.
Если "разумный" человек, берётся за постройку целого дома, более-менее представляя как пользоваться только молотком, то у меня вопрос о его разумности стоит под большим сомнением) Потому что в конечном счёте это выйдет ему гораздо дороже, как если бы он просто купил новый дом)
Хочешь остаться довольным, научись делать сам. Свои идеи я пытался продвинуть, упрашивая разработчика сделать каждый шаг. В результате везде недодел. А недоделанное это фактически ничто. И выходит это очень долго. И самое обидно в конце концов остаться не удел и выслушивать гадость по поводу того, что идеи ничего не значат, а вот именно код... Тогда почему программистов пруд пруди, а программ... Согласен, что должно быть все идеально и я предлагал работать совместно тем программистам. Закончилось все банальным плагиатом. Ну в общем тебе надо ты и делай. Делаю :). Хватит тянуться за соседом, надо просто сделать лучше.
Я понимаю, что опыт тоже очень важен и на одной теории так просто далеко не едешь. Но чтоб этот опыт приносил пользу нужно всё же параллельно и инструмент изучать и хвататься не за дом сразу, а скажем за табуретку, ну или за маленький домик для собаки)
Так а с чего вы взяли, что параллельно я ничего не читаю? Разве возможно сделать то, что я делаю не заглядывая в букварь, справочник...
- Заглядываю в справочники.
- Чужие примеры, исходники.
- Видеоуроки.
- Гуглю.
- Вопросы на форуме (очень важный момент, научиться не стесняться спрашивать, кто бы вам чего не наговорил).
Другое дело, что я не читаю учебник или справочник последовательно. Это бессмысленно. Есть задачка, важно знать где копнуть и пытаюсь воспроизвести, попутно приходит осознание происходящего. Конечно не совсем в буквальном смысле. Исходники слава богу по порядку могу читать и связать составляющие, особенно если не лениться :). Но конечно заглянув в справочник и увидев там новую конструкцию без реального примера, мало похожую, что на самом деле в исходнике, сложнова-то  правильно ее применить.

Все лирики больше не будет. Надо как то связать эти два варианта ввода информации и выдать для критики :).


Название: Re: Регулярное выражение с QString
Отправлено: Spark от Август 15, 2013, 20:55
Застрял.
Допустим создал и заполнил QStringList compoundList в compoundWord.cc. Не получается передать его в mainwindow.cc. Как попроще это сделать?


Название: Re: Регулярное выражение с QString
Отправлено: Spark от Август 17, 2013, 17:45
Из mainwindow.cc добавляю пункты списка:
Код
C++ (Qt)
textory.addItem(Textory::Item(1, compoundWordItem));

Список находится в textory.cc:
Код
C++ (Qt)
void Textory::addItem( Item const & item )
{
 
...
 
  qDebug() << "adding item " << addingItem;
 
 emit itemsChanged();
}
Нет проблем с добавлением. Т.е. найденные слова добавляются в список и самое главное :) отправляется сигнал:
Код
C++ (Qt)
emit itemsChanged()

Создаю compound.cc для поиска спец. пунктов. Срабатывает:
Код
C++ (Qt)
textory.addItem(Textory::Item(1, compoundWordItem));
Пункты доходят, о чем свидетельствует qDebug. Но вот сигнал при этом не срабатывает. Где могут быть грабли? На что обратить внимание?


Название: Re: Регулярное выражение с QString
Отправлено: kambala от Август 17, 2013, 18:24
видимо сигнал не соединен со слотом в compound


Название: Re: Регулярное выражение с QString
Отправлено: Spark от Август 17, 2013, 18:54
Compound.cc занимается поиском специальных пунктов списка и отправляет их в textory.cc. Который уже формирует сам список:
Код
C++ (Qt)
void Textory::addItem( Item const & item )
{
 
  items.prepend( item );
 
  qDebug() << "adding item " << addingItem;
 
 emit itemsChanged();
}
Сам же слот для этого сигнала находится в textorywidget.cc, который обновляет список на экране.
Вроде все просто и сами пункты доходят до void Textory::addItem( Item const & item ). Но вот с сигналом траблы.
Это при том, что отправляя пункты из mainwindow.cc в эту же функцию все работает нормально. И срабатывает эта связка SIGNAL->SLOT. Список  светится на экране :). Но вот спецсписок вывести не удается.
Вообще экспериментировал с другими слотами, не запускаются они если информация в textory.cc пришла не с mainwindow.cc.

Казалось главное доставить пункты до textory.cc, а там уже все само собой :). Доставил, но не тут то было, для меня.

Дело в том, что создавая на основе других исходников, конечно же допускаю ошибки. Надеюсь на то, что не очевидное для меня очевидно для специалистов и помогут разобраться. Может я допускаю типичные ошибки.


Название: Re: Регулярное выражение с QString
Отправлено: Spark от Август 17, 2013, 19:04
В textorywidget.cc есть уже такой слот:

Цитата: cpp
void TextoryModel::textoryChanged()
{
  qDebug() << "Textory Changed!";

  reset();
}

И qDebug показывает, что до него все уже доходит если пункт был отправлен через mainwindow.cc.


Название: Re: Регулярное выражение с QString
Отправлено: Spark от Август 17, 2013, 19:20
Может не ясно описал ситуацию. Схематично:
Эта связка работает:
mainwindow.cc (доставка Item - работает) -> textory.cc  (сигнал-слот работает) -> textorywidget.cc

Эта связка не работает:
Compound.cc (доставка Item - работает) -> textory.cc  (сигнал-слот не работает) -> textorywidget.cc


Название: Re: Регулярное выражение с QString
Отправлено: Spark от Август 17, 2013, 20:19
Может как то хитро можно продиагностировать сигнал-слот?


Название: Re: Регулярное выражение с QString
Отправлено: kambala от Август 17, 2013, 20:51
видимо сигнал не соединен со слотом в compound
это значит, что ты connect не написал где-то в Compound.cc. посмотри как соединяется тот объект типа Textory в mainwindow.cc и сделай аналогично в Compound.cc. по волшебству сигналы и слоты не соединяются.


Название: Re: Регулярное выражение с QString
Отправлено: Spark от Август 17, 2013, 21:33
Запутался. Тут вроде и не нужно было прописывать connect. Вроде все по аналогии делал. Но ведь дело не в:
Compound.cc (доставка Item - работает) -> textory.cc.
Здесь все работает. Qlist перегоняется, так же хорошо как и в связке:
mainwindow.cc (доставка Item - работает) -> textory.cc.

Ведь проблема дальше в textory.cc  (сигнал-слот работает) -> textorywidget.cc. Здесь вроде я вообще ничего не должен был трогать и все работать должно было. Тем не менее, если слив списка был произведен из mainwindow.cc то все в порядке. Слот срабатывает.
Но если перелить тот список из Compound.cc. То этот слот уже не срабатывает.

Сигнал опубликован в textory.hh.
signals:
  void itemsChanged();

И он работает в textorywidget.cc:
Код
C++ (Qt)
 connect( m_textory, SIGNAL( itemsChanged() ),
          this, SLOT( updateTextoryCounts() ) );

textorywidget.hh:
Код
C++ (Qt)
private:
 Textory * m_textory;

Но только так как я описал выше.


Название: Re: Регулярное выражение с QString
Отправлено: kambala от Август 17, 2013, 22:01
ты правда думаешь, что по не очень понятным кусочкам кода можно что-то сказать? словесное описание это безусловно хорошо, но не отображает реальной картины. непонятно от кого наследуются классы, от которых ты называешь только имена файлов, и непонятно как именно они взаимодействуют между собой (на уровне кода, словесно цепочку ты уже описывал).

пальцем в небо: раз коннект находится только в textorywidget, значит там скорее всего m_textory является указателем не на тот textory, который сидит в Compound. можно проверять что возвращает коннект (true/false).


Название: Re: Регулярное выражение с QString
Отправлено: Spark от Август 18, 2013, 05:59
Хорошо. Наверное действительно путанно пояснил.

Постараюсь пояснить проще.
Есть textory.cc  и в ней функция:
Код
C++ (Qt)
void Textory::addItem( Item const & item )
{
  list.prepend( item );
  emit itemsChanged();
}
Как видим, эта функция просто принимает пункты списка и формирует сам список. При получении очередного пункта списка отправляет сигнал.

Принимающий слот находится в textorywidget.cc:
Код
C++ (Qt)
 connect( m_textory, SIGNAL( itemsChanged() ),
          this, SLOT( updateTextoryCounts() ) );
И все. Эта схема работает.
Если список list гарантированно формируется в любом случае, то почему с сигналом траблы? Он срабатывает только тогда когда пункт списка пришел с mainwindow.cc.

Мои скромные познания не позволяют увидеть связь или проверить, что мешает отправить (или принять) сигнал, если пункт списка пришел с compound.cc. Как я понимаю, отправится сигнал должен был, но что то мешает принять его.


Название: Re: Регулярное выражение с QString
Отправлено: Spark от Август 18, 2013, 06:14
Или я могу заблуждаться по поводу того, что список формируется?
Просто qDebug показывает, что пункты списка приходят в любом случае:
Код
C++ (Qt)
void Textory::addItem( Item const & item )
{
  list.prepend( item );
  qDebug() << "adding item " << item.word;
  emit itemsChanged();
}
Может просто сам список не пополняется? И искать причины в другом месте?


Название: Re: Регулярное выражение с QString
Отправлено: Spark от Август 18, 2013, 07:27
В textorywidget.cc проверяю коннек, надеюсь правильно понял как это делается.
Код
C++ (Qt)
 connect( m_textory, SIGNAL( itemsChanged() ), this, SLOT( updateTextoryCounts() ) );
 qDebug() << "CONNECT " << connect( m_textory, SIGNAL( itemsChanged() ), this, SLOT( updateTextoryCounts() ) );

В дебаге при запуске:
CONNECT  true

Вернее, наверное вопрос надо ставить так. Как правильно узнать, что возвращает connect каждый раз при отправке сигнала?


Название: Re: Регулярное выражение с QString
Отправлено: kambala от Август 18, 2013, 10:38
непонятно от кого наследуются классы, от которых ты называешь только имена файлов, и непонятно как именно они взаимодействуют между собой (на уровне кода, словесно цепочку ты уже описывал).
ничего из того, что я просил написать, почему-то не написано.

результат коннекта проверен правильно.

поставь брейкпоинт в методе updateTextoryCounts() чтобы убедиться, что туда программа действительно не заходит.
раз коннект находится только в textorywidget, значит там скорее всего m_textory является указателем не на тот textory, который сидит в Compound
а вот это проверял? делается с помощью вывода адреса памяти, в котором сидит объект: qDebug() << m_textory или qDebug() << &textory
В textorywidget.cc есть уже такой слот:

Цитата: cpp
void TextoryModel::textoryChanged()
{
  qDebug() << "Textory Changed!";

  reset();
}

И qDebug показывает, что до него все уже доходит если пункт был отправлен через mainwindow.cc.
а этот слот тут собственно при чем? коннект же сделан с updateTextoryCounts(). или он там вызывается из updateTextoryCounts()?


Название: Re: Регулярное выражение с QString
Отправлено: Spark от Август 18, 2013, 12:26
а этот слот тут собственно при чем? коннект же сделан с updateTextoryCounts(). или он там вызывается из updateTextoryCounts()?
Да тут спутал (наэкспериментировал). Так правильно:
Код
C++ (Qt)
void TextoryModel::updateTextoryCounts()
{
 qDebug() << "Textory Changed!";
 reset();
}

Сейчас постараюсь перевести то, что вы мне посоветовали :).
поставь брейкпоинт в методе updateTextoryCounts() чтобы убедиться, что туда программа действительно не заходит.
Разве это не пойдет для проверки?:
Код
C++ (Qt)
void TextoryModel::updateTextoryCounts()
{
 qDebug() << "Textory Changed!";
 reset();
}
Textory Changed! высвечивается, только тогда пункты списка начинают лететь с maiwindow.cc.


Название: Re: Регулярное выражение с QString
Отправлено: Spark от Август 18, 2013, 12:51
а вот это проверял? делается с помощью вывода адреса памяти, в котором сидит объект: qDebug() << m_textory или qDebug() << &textory
Как смог так понял :).
В общем в textorywidget.cc - M_Textory1  Textory(0x28f80c)
В mainwindow.cc - Textory2  Textory(0x28f80c)
В compound.cc Textory3 - Textory(0xb94b0b4)
Ну разницу вижу :). Спасибо, теперь хоть видно что копать. Но не ясно где :). Буду разбираться почему так?

P.S. Так по простому понял - как только циферки совпадут, так все сразу наладится :)?


Название: Re: Регулярное выражение с QString
Отправлено: kambala от Август 18, 2013, 13:12
P.S. Так по простому понял - как только циферки совпадут, так все сразу наладится :)?
да. где-то в mainwindow передается объект Textory (или указатель на него) в textorywidget, который сохраняется в последнем. тебе надо сделать то же самое в compound.


Название: Re: Регулярное выражение с QString
Отправлено: Spark от Август 18, 2013, 13:46
P.S. Так по простому понял - как только циферки совпадут, так все сразу наладится :)?
да. где-то в mainwindow передается объект Textory (или указатель на него) в textorywidget, который сохраняется в последнем. тебе надо сделать то же самое в compound.
Спасибо с вашей помощью победил.
Однако нагородил чувствую огород :). Поскольку, фактически шел на поводу у компилятора. Что он просил, то и делал. В общем это касается переменных, которые надо объявить. Если компилятор ругается на их отсутствие, то объявляю и прописываю где просят :). Как то так на ощупь в данном случае. Это немного гнетет. Поскольку, скорее всего можно было как то оптимально сработать. Не то, что не понимаю, что делаю, а просто некоторые вещи кажутся лишними. Надеюсь сейчас буду переписывать на чисто и более осознанно смотреть, что лишнее.
Но главное работает. И заветный списочек выводится :). Подготовил его относительно быстро, а вот пару дней провозился на его вывод. Теперь приобрел еще небольшой навык и по диагностике.
Спасибо!


Название: Re: Регулярное выражение с QString
Отправлено: Spark от Август 18, 2013, 19:38
Пытаюсь с compound.cc отправить пункты списка прямо в mainwindow.cc минуя textory.cc.
Допустим, делать это через слот:
emit listStatCompound( compoundWordItem );
Если действовать по аналогии то с виду ничего сложного.
Однако, одна пугающая загвоздка. В mainwindow.cc требуется объявить:
m_compound( длинная цепочка переменных ),

Мало того, что мне надо то перетащить только пункты QStringlist. К тому же я не знаю, что именно объявлять в скобках, если мне это вообще не нужно, не объявлять же кучу ненужных переменных, что бы просто их вставить в эту цепочку. Как я собственно выкрутился в предыдущей задаче (благо там только одна переменная понадобилась и я ее воткнул с потолка, как мне кажется :)).
Ну понимаю, что меня можно в чем поругать и на на этот раз и поделом :). Когда выполнял подобные задачи, создавая свои виджеты, то подобные вопросы были более проще, поскольку самостоятельно постепенно все прописывал и понимал, что делаю. Но в данном случае ковыряю не свой исходник, добавив свой функционал и все, что в нем прописано ранее, конечно, нужно. Но теперь требуется соединить поток с mainwindow.cc. И можно ли как то выкрутиться и на этот раз? Надеюсь ясна ситуация.

Или задача перелива списка решается как то проще?


Название: Re: Регулярное выражение с QString
Отправлено: kambala от Август 18, 2013, 20:53
в третий раз спрашиваю: какая взаимосвязь между твоими классами? что такое compound (виджет или просто класс с данными)? где и как он создается?


Название: Re: Регулярное выражение с QString
Отправлено: Bepec от Август 18, 2013, 20:56
to kambala:
На сколько тебя ещё хватит, интереcно :)


Название: Re: Регулярное выражение с QString
Отправлено: gil9red от Август 18, 2013, 21:15
Блин, переливание из пустого в порожнее :-\


Название: Re: Регулярное выражение с QString
Отправлено: Spark от Август 18, 2013, 21:22
в третий раз спрашиваю: какая взаимосвязь между твоими классами? что такое compound (виджет или просто класс с данными)? где и как он создается?
Попробую ответить на вопрос так как я это понимаю.
Класс с данными. Создается в новом листинге. Вернее он был создан до меня. Добавил свой функционал и пытаюсь научиться обмениваться данными между классами в разных листингах.


Название: Re: Регулярное выражение с QString
Отправлено: Spark от Август 18, 2013, 21:26
Критиков всегда больше, чем желающих помочь. Но в подобных комментариях нет нужды.


Название: Re: Регулярное выражение с QString
Отправлено: kambala от Август 18, 2013, 21:27
нет слов, одни матыэмоции

хорошо, в каком месте создается объект типа compound? каким образом (через какие другие классы, если такие есть) он связан с mainwindow?


Название: Re: Регулярное выражение с QString
Отправлено: Spark от Август 18, 2013, 21:34
Хорошо. У нас уже очень поздно. Надо отдохнуть. Попытаюсь завтра ответить на вопросы.


Название: Re: Регулярное выражение с QString
Отправлено: gil9red от Август 18, 2013, 21:44
Критиков всегда больше, чем желающих помочь. Но в подобных комментариях нет нужды.
Просто перед тем как работать с инструментом, нужно прочитать его инструкцию :)
Я понимаю, у вас нет времени читать инструкцию - хочется сразу же узнать как работать на нем и получить нужный вам результат :)


Название: Re: Регулярное выражение с QString
Отправлено: Spark от Август 19, 2013, 05:54
Читал и читаю инструкции и не только. Без практики они мало чего дают и дают медленный результат. Да взял тему для разработок не для новичка. Но и с успехом ее реализовываю. В общем то результат достигнут. Но я хочу аккуратнее и разобраться поглубже. Бессмысленные темы попроще они мне не интересны. Никогда и не скрывал, что много не понимаю и шаг влево/вправо бывает дается относительно не просто. Но в целом не вижу трудностей. Все решаемо. Понять меня сложно, так же как мне вас. Что от меня требуется. Разговариваем на разных языках. Хотя на поверку оказывается не так все сложно. Нужно быть чуточку внимательней и раньше я это об этом читал, а сейчас на практике приходится осознавать. В общем чем дальше тем меньше белых пятен. И эту закроем.

P.S. Тем кто терпимее относится к новичкам/ученикам спасибо. Надо-ж нас учить уму разуму.


Название: Re: Регулярное выражение с QString
Отправлено: Spark от Август 19, 2013, 07:19
хорошо, в каком месте создается объект типа compound? каким образом (через какие другие классы, если такие есть) он связан с mainwindow?
Попробую осознать, что от меня требуется:
В каком месте:
- Для трансплантации выбрана довольно сложная программа, как для новичка - многолистинговая.
- В mainwindow.cc объявлен, относительно не сложно, класс:
Код
C++ (Qt)
MainWindow::MainWindow( Config::Class & conf_ ):
далее перечисляются переменные. Среди них нет compound.
- В compound.cc заявлен класс:
Код
C++ (Qt)
Compound::Compound(Config::Class & conf_,
 QString const & wrd_, QString const & grup_,
 QMap< QString, QString > const & ctexts_,
 vector< sptr< Textionary::Class > > const & activeTexts_,
 string const & heder,
 int limitSize, bool needExpand_,
 Textory & textory_ ):
   conf( conf_ ),
   textory( textory_ ),
   wrd( wrd_ ), grup( grup_ ), ctexts( ctexts_ ),
   activeTexts( activeTexts_ ),
   altDone( false ), bodDone( false ), foundDefinitions( false ),
   closePrev( false ),
   artSizeLimit( sizeLimit),
   needExpand( needExpand_ )

Это:
Compound::Compound(Config::Class & conf_,
и это:
  Textory & textory_ ):
    conf( conf_ ),
    textory( textory_ ),

Добавлял уже я, что бы решить предыдущую задачу для перелива списка compound.cc -> textory.cc -> textorywidget.cc

Теперь хочу решить эту задачу иным способом:
В compound.cc создается переменная типа QStringlist. Задача перелить этот список в mainwindow.cc.


Название: Re: Регулярное выражение с QString
Отправлено: Igors от Август 19, 2013, 09:26
Теперь хочу решить эту задачу иным способом:
В compound.cc создается переменная типа QStringlist. Задача перелить этот список в mainwindow.cc.
Выложите compound.cc и compound.h, прокомментировав то место где создается QStringList. А так Вы попусту тратите свое и чужое время


Название: Re: Регулярное выражение с QString
Отправлено: kambala от Август 19, 2013, 11:13
ну никак ты не желаешь показать взаимосвязь MainWindow и Compound. какое-то связующее звено ведь между ними должно быть, иначе ты не сможешь решить поставленную перед собой задачу.

объявление класса начинается со слова class, а то, что ты показал — это реализация конструктора.

заявляют в миполицию, а классы и переменные объявляют.

P.S. хватит уже всем сообщать какой ты крутой новичок, что работаешь с серьезным проектом — чуть ли не на каждой странице присутствует подобное сообщение. лучше бы изучал основы языка.


Название: Re: Регулярное выражение с QString
Отправлено: Spark от Август 19, 2013, 12:44
В общем то я и не думал хвастаться. Только хотел подчеркнуть, что задача не из легких для новичка и при этом я много не понимаю, по этому не могу с ходу понять, что именно от меня требуется. Но раз это так выглядит, значит перебарщиваю и постараюсь избежать подобного.
Хорошо, может действительно не с того конца лучину жгу. Не хочу вас больше раздражать. Попробую самостоятельно разобраться.


Название: Re: Регулярное выражение с QString
Отправлено: Majestio от Август 20, 2013, 10:17
Критиков всегда больше, чем желающих помочь. Но в подобных комментариях нет нужды.

Желание помогать пропадает ровно тогда, когда "спрашающий" тупо игнорирует данные ему ответы, ссылаясь на собственную концепцию обучения программированию. Если вы выбрали столь суровый путь познания, с какого перепугу вы недовольны, что все остальные не идут за вами? :-\

Я честно хотел вам помочь. Предложил вам две основополагающие вещи:

1) Четкую постановку задачи в виде ТЗ
2) Доступность ваших текущих исходников (sourceforge или git)

Вы это продинамили. Ну что же, это ваш путь - но нам с вами не по пути.
Теперь заглядывать буду наверное чисто из любопытства.


Название: Re: Регулярное выражение с QString
Отправлено: Igors от Август 20, 2013, 10:32
Код
C++ (Qt)
Compound::Compound(Config::Class & conf_,
 QString const & wrd_, QString const & grup_,
 
Насколько я понял, по каким-то причинам выложить исходники нельзя. Ну что, тогда опишите ф-ционал класса Compound. Судя по приведенному конструктору его надо сносить и писать заново. Информации мало, но есть мнение что латая чужой код Вы потратите куда больше времени, но так и не добьетесь цели. И здесь дело совсем не в "опыте"  (упоминаниями о которм Вы уже задолбали). Просто есть какой-то предел дальше которого нельзя "подправить" а только "переписать".


Название: Re: Регулярное выражение с QString
Отправлено: Spark от Август 22, 2013, 09:04
Да, действительно есть причины не позволяющие пока опубликовать исходники. Поэтому извините, если, что не так. Надеюсь месяца через полтора опубликую и все встанет на свои места.
В данном случае просто рассчитывал получить указания по поводу очевидных, типичных ошибок, которые мог упустить.

Ну а по вопросу, решил воспользоваться советами. Отдохнул, посмотрел в окно, затапливают нас, есть над чем поразмыслить :).
Свежий взгляд разрулил ситуацию. Оказалось не так и сложно. Textory.cc транзитный класс для mainwindow.cc на пути к выводу списка через виджет texorywidget.cc. А для compound.cc его сделать транзитным относительно не сложно.

Как помните в mainwindow.cc воткнул функцию WordStat. Статистика относительно проста - подсчитать слова и рассортировать.
В compound.cc организовал поиск фраз. И этот список пытался доставить в mainwindow.cc для смешивания с остальной статистикой и сортировкой.
А поскольку особого труда не составило перелить данные из compound.cc в Textory.cc и из mainwindow.cc в тот же Textory.cc...
Короче переписал WordStat в Textory.cc. Здесь уже проще смешать данные, сделать, что надо и вывести на экран.
Спасибо за то, что так или иначе уму разуму учите. Знать в каком направлении двигаться и быть уверенным, что там ищешь - это уже не плохо.


Название: Re: Регулярное выражение с QString
Отправлено: Igors от Сентябрь 29, 2013, 05:57
Цитировать
Малыш ползает по ковру и видит спрятавшегося под кроватью любовника

- ну сто, не дысыс? А как дысал, как дысал!
Так чем же кончилось столь резвое изучение программирования?  :)