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

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

Страниц: [1] 2 3   Вниз
  Печать  
Автор Тема: Вопрос о сравнении вхождений QStringList'ов  (Прочитано 14428 раз)
Alexander
Гость
« : Февраль 13, 2010, 15:22 »

Начал изучать Qt совсем недавно и на сей момент столкнулся с достаточно простой проблекой, но... Помогите, кто сможет)

Есть переменная QStringList Token, в которой хранится список введенных пользователем слов. В другую переменную QStringList StopList, при старте программы, загружается список "стоп" слов, которые нужно удалить из списка первой переменной. Понимаю, что весь алгоритм сводится к сравнению элементов списков и при нахождении совпадений - удалению, но не получается....

Сим кодом загружается список "стоп" слов:

Код:
void Tokenizer::loadStopWord() {
    QFile stopword (qApp->applicationDirPath()+"/files/stop_word_list.txt");
    if (!stopword.open(QIODevice::ReadOnly|QIODevice::Text))
    {
        QMessageBox msgBox;
        msgBox.setText("Can't load the file Stop_word_list.txt!");
        msgBox.exec();
    }
    QTextStream stopwordStream(&stopword);
    while (!stopwordStream.atEnd())
    {
      StopList.append((stopwordStream.readLine()).toLower());
    }
}

Далее часть функции tokenization должна собственно сравнивать строки:

Код:
void Tokenizer::tokenization() {
int t=0;
while (t!=-1)
{
    for (int i=0; i<StopList.length(); i++)
    {
        if (StopList[i]==Token[t])
            Token.removeAll(Token[t]);
    }
t--;
}
ui->Token_list->addItems(Token);
}

Но в результате программа возвращает просто значение Token.
Записан
BRE
Гость
« Ответ #1 : Февраль 13, 2010, 15:43 »

t = 0; после первой итерации t становится равно -1, цикла завершается...
Проверяем только первое слово из Token.

Записан
Alexander
Гость
« Ответ #2 : Февраль 13, 2010, 16:14 »

Логично... =) А чему же тогда должен быть равен t?
Записан
BRE
Гость
« Ответ #3 : Февраль 13, 2010, 16:23 »

Логично... =) А чему же тогда должен быть равен t?
Наверное, количеству элементов в Token:
Token.size()
Записан
Alexander
Гость
« Ответ #4 : Февраль 13, 2010, 16:41 »

переписал так:

Код:
int t=Token.size();
while (t!=-1) ...

выдает Runtime Error
Записан
Kolobok
Гость
« Ответ #5 : Февраль 13, 2010, 17:23 »

Код:
foreach(QString s,StopList)
  Token.removeAll(s);
Записан
Alexander
Гость
« Ответ #6 : Февраль 14, 2010, 06:20 »

Спасибо! С foreach работает)

Но чтобы не оставалось так сказать пробелов в знаниях, как можно было бы переписать код,используя while?

Пробовал использовать также цикл с
Код:
for (int t=0; t<Token.length(); t++)
и вроде бы итерации шли до конца, но вот почему-то не все "стоп" слова удалялись из списка Token, а как-то выборочно. И если сами "стоп" слова запихать в Token и обработать,то возникала опять же Runtime Error. В чем может быть ошибка? Код соответственно такой же, только с for:
Код:
for (int t=0; t<Token.length(); t++)
{
    for (int i=0; i<StopList.length(); i++)
    {
        if (StopList[i]==Token[t])
            Token.removeAll(Token[t]);
    }
}
Записан
niXman
Гость
« Ответ #7 : Февраль 14, 2010, 09:10 »

по взрослому, делается так:
Код
C++ (Qt)
std::list<std::string> tokens = {"1", "2", "3", "3", "6", "2", "9"};
tokens.sort(); // обязательно сортируем
std::list<std::string> stop_list = {"7", "2", "3", "5"};
stop_list.sort(); // обязательно сортируем
 
std::set_intersection(stop_list.begin(), stop_list.end(),
 tokens.begin(), tokens.end(),
 [&](auto x) { std::remove(tokens.begin(), tokens.end(), *x); } // внимание лямбда!
 );
 
но нужен компилятор gcc-4.5.0

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

кстати вместо лямбда, можно использовать функтор с перегруженным operator()
Записан
niXman
Гость
« Ответ #8 : Февраль 14, 2010, 09:28 »

кстати, для того чтоб не было гемора с индексами, выходом за пределы - изобрели итераторы Подмигивающий
Записан
Alexander
Гость
« Ответ #9 : Февраль 14, 2010, 11:06 »

2 niXman
Спасибо за код, попытаюсь разобраться в нем) Но пока, что лямбда, что функтор, всё звучит для меня одинаково... Грустный

И еще, был бы признателен за информацию о том, что такое многомерные массивы в C++ Qt, и как с ними правильно работать, как многомерный массив оформить в txt файле. =)
Записан
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« Ответ #10 : Февраль 15, 2010, 06:07 »

На контейнерах можно так
Код:
void RemoveStopsFromLst( QStringList & lst, const QStringList & stopLst )
{
// QSet для быстрого поиска
  QSet <QString> stop = stopLst.toSet();

// выходной лист чтобы не связываться с мутными удалениями из контейнера
  QStringList dst;

// отбираем
  for (int i = 0; i < lst.size(); ++i)
   if (!stop.contains(lst[ i ])
    dst.push_back(lst[ i ]);

// переписываем
  lst = dst;
}
Записан
Alexander
Гость
« Ответ #11 : Февраль 15, 2010, 13:03 »

А есть ли какие-то отличия в работе этих трех вариантов кода? Если да, то какие и где?)

Код:
foreach(QString s,StopList)
  Token.removeAll(s);

Код:
std::list<std::string> tokens = {"1", "2", "3", "3", "6", "2", "9"};
tokens.sort(); // обязательно сортируем
std::list<std::string> stop_list = {"7", "2", "3", "5"};
stop_list.sort(); // обязательно сортируем
 
std::set_intersection(stop_list.begin(), stop_list.end(),
  tokens.begin(), tokens.end(),
  [&](auto x) { std::remove(tokens.begin(), tokens.end(), *x); } // внимание лямбда!
  );

и

Код:
void RemoveStopsFromLst( QStringList & lst, const QStringList & stopLst )
{
// QSet для быстрого поиска
  QSet <QString> stop = stopLst.toSet();

// выходной лист чтобы не связываться с мутными удалениями из контейнера
  QStringList dst;

// отбираем
  for (int i = 0; i < lst.size(); ++i)
   if (!stop.contains(lst[ i ])
    dst.push_back(lst[ i ]);

// переписываем
  lst = dst;}
Записан
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« Ответ #12 : Февраль 15, 2010, 16:51 »

А есть ли какие-то отличия в работе этих трех вариантов кода? Если да, то какие и где?)
Лучше спросить о достоинствах каждого варианта, тогда

1) Краткость/лаконичность

2) Демонстрация богатых возможностей библиотеки (и своей эрудиции)

3) Скорость
Записан
niXman
Гость
« Ответ #13 : Февраль 15, 2010, 22:10 »

Цитировать
2) Демонстрация богатых возможностей библиотеки
естественно! как писать идеальный код на С++ не зная STL и стандарта С++.

Цитировать
и своей эрудиции
вам знакомо? -
Код
C++ (Qt)
учиться, учиться, еще раз учиться(как-то так)...
не вижу ничего плохого в этом.

Цитировать
3) Скорость
Смеющийся

вот где скорость:
Код
C++ (Qt)
std::list<std::string> tokens = {"1", "2", "3", "3", "6", "2", "9"};
tokens.sort(); // обязательно сортируем
std::list<std::string> stop_list = {"7", "2", "3", "5"};
stop_list.sort(); // обязательно сортируем
 
std::list<std::string> dst;
 
std::set_intersection(stop_list.begin(), stop_list.end(),
 tokens.begin(), tokens.end(),
                                                 std::back_inserter(dst)
                         );
 

Igors
кстати, забыли упомянуть о "независимости" от сторонних библиотек, соответствии стандарту программирования, и 100% переносимости кода.
Записан
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« Ответ #14 : Февраль 16, 2010, 10:29 »

Код:
tokens.sort(); // обязательно сортируем
А кто Вам разрешил менять порядок слов в списке? Извольте повоэиться с указателями, посмотрим как вырастет объемчик.

кстати, забыли упомянуть о "независимости" от сторонних библиотек, соответствии стандарту программирования, и 100% переносимости кода.
Да, об этом мне лучше промолчать, потому что каждый раз когда я перетаскиваю сделанное c Mac на Вындоуз MSVC - я с ужасом думаю какую еще подлянку мне подсунет мелкософт и сколько дней (или недель) уйдет на то чтобы весь STL работал в Debug и Release

естественно! как писать идеальный код на С++ не зная STL и стандарта С++.
Никто и не говорил что не нужно знать стандарт. Вот только мне кажется что лучше не тот программист, который больше знает, а который умеет искать и находить решения.
« Последнее редактирование: Февраль 16, 2010, 10:31 от Igors » Записан
Страниц: [1] 2 3   Вверх
  Печать  
 
Перейти в:  


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