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

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

Страниц: 1 2 3 [4] 5 6 ... 18   Вниз
  Печать  
Автор Тема: Регулярное выражение с QString  (Прочитано 160913 раз)
Spark
Гость
« Ответ #45 : Июль 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. Будем обдумывать новые предложения.
« Последнее редактирование: Июль 26, 2013, 13:59 от Spark » Записан
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« Ответ #46 : Июль 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 в исходном тексте. Ну типа проверка архитектуры на вшивость Улыбающийся Что бум делать?
Записан
Spark
Гость
« Ответ #47 : Июль 26, 2013, 15:16 »

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

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

Вторая стадия будет заключаться в более глубоком анализе текста. Надеюсь осилю.
« Последнее редактирование: Июль 26, 2013, 16:31 от Spark » Записан
Spark
Гость
« Ответ #48 : Июль 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

и.т.д.
В целом смысл ясен. Но вот опять же опыта маловато, что бы с легкостью это делать. Конечно в идеале раз увидеть как это последовательно делается. Либо более долгий путь ковырять исходники примеров и постепенно выстраивать свою структуру. Пока протаптываем дорожки и бегаем по проторенным. Как нибудь и эту протопчим Улыбающийся.
Записан
Spark
Гость
« Ответ #49 : Июль 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) );
       }
Надо понять как расположить в порядке частотности и каким образом оставить нужный язык с списке.
Любой помощи рад.
Записан
Old
Джедай : наставник для всех
*******
Online Online

Сообщений: 4350



Просмотр профиля
« Ответ #50 : Июль 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() );
 
« Последнее редактирование: Июль 26, 2013, 19:20 от Old » Записан
Majestio
Гость
« Ответ #51 : Июль 26, 2013, 22:27 »

Сравните пока с этим, а если будет нужно, я уберу регулярку и тогда вы удивитесь еще больше. Улыбающийся

Не поленился - сравнил.
Если интересно, смотрите тут (для Qt 5.0.2).

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

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

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

Считаю ваше утверждение об "оптимальности" несколько натянутым. Если в общем зачете, вы - отстаете. Если будем под оптимальностью понимать исключительно скорость - тогда я только за asm, только за хардкор!  Смеющийся
Записан
Majestio
Гость
« Ответ #52 : Июль 26, 2013, 22:41 »

ЗЫ: Чет мой провайдер hostinger.ru зашалил ... восстановится, сможете тестовый проект качнуть.
Записан
Old
Джедай : наставник для всех
*******
Online Online

Сообщений: 4350



Просмотр профиля
« Ответ #53 : Июль 26, 2013, 22:50 »

1) Ваш код работает на 1/5 быстрее моего
А у меня другие результаты:
8 ms против 28 ms - это если использовать именно QHash как я и писал у себя или
15 ms против 28 ms - это если "уравнивать условия" по вашему.
О каких 1/5 идет речь?
Записан
Old
Джедай : наставник для всех
*******
Online Online

Сообщений: 4350



Просмотр профиля
« Ответ #54 : Июль 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... Улыбающийся

По поводу разного расхода памяти вы сами знаете или нужны пояснения? Улыбающийся
« Последнее редактирование: Июль 26, 2013, 23:11 от Old » Записан
Majestio
Гость
« Ответ #55 : Июль 26, 2013, 23:09 »

Вот тест для 100 итераций:

Вы регэкспы уравняйте, это тоже существенно))
Записан
Old
Джедай : наставник для всех
*******
Online Online

Сообщений: 4350



Просмотр профиля
« Ответ #56 : Июль 26, 2013, 23:12 »

Вы регэкспы уравняйте, это тоже существенно))
Читайте выше, все уровнял. Подмигивающий
И даже результаты можно посмотреть.

А если от регулярки отказаться, то будет совсем грустно. И это с огромным оверхедом по памяти в вашем варианте.
« Последнее редактирование: Июль 26, 2013, 23:14 от Old » Записан
Majestio
Гость
« Ответ #57 : Июль 26, 2013, 23:31 »

Вы регэкспы уравняйте, это тоже существенно))
Читайте выше, все уровнял. Подмигивающий
И даже результаты можно посмотреть.

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

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

Это тут - http://majestio.tk/soft/Words-2.7z
Записан
Old
Джедай : наставник для всех
*******
Online Online

Сообщений: 4350



Просмотр профиля
« Ответ #58 : Июль 26, 2013, 23:40 »

Если вы не против - я кину исходник, проверьте, подправьте. Все пояснения если чего - с меня)
Лучше я выложу свой проект.
Записан
Majestio
Гость
« Ответ #59 : Июль 27, 2013, 00:04 »

Если вы не против - я кину исходник, проверьте, подправьте. Все пояснения если чего - с меня)
Лучше я выложу свой проект.
Оке, завтра гляну. Там результаты выводятся или только код парсинга?
Записан
Страниц: 1 2 3 [4] 5 6 ... 18   Вверх
  Печать  
 
Перейти в:  


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