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

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

Страниц: [1]   Вниз
  Печать  
Автор Тема: ::iterator, ::const_iterator  (Прочитано 7229 раз)
SABROG
Гость
« : Июнь 07, 2007, 15:42 »

Вопрос не столько по Qt, сколько по самому программированию на C++.
Есть QVariantList (QList<QVariant>). В нем список уникальныйх intовых значений. Хочу убрать из листа несколько или все значения не подходящие мне по условию. Чтобы на выходе лист содержал либо все эти значений, либы все без удаленных, либо был пустым. Но я не хочу создавать второй (временный) лист. Если цикл оформлять через .size() и удалять ненужные значения через removeAt(i), то цикл вероятно будет выполняться, скажем, раз 30, хотя под конец список может быть уже и пустым, а значит я получу exception. Если делать через ::iterator, то цикл выполняется с одним и тем же указателем ровно такое количество раз, сколько было удалено значений. Т.е. я удаляю скажем 3 значения, цикл выполняет 3 пустых итераций на следующем значении с одним и тем же указателем. Но у меня в цикле идут Selectы к базе, поэтому мне совсем не кстати, скажем 200 бесполезных запросов. Пытался сделать через const_iterator, но все тоже самое. Видимо я не совсем понимаю логику его работы.
Записан
Alex Forth
Гость
« Ответ #1 : Июнь 07, 2007, 16:09 »

Покури мануал по

template <class ForwardIterator, class Predicate>
ForwardIterator remove_if(ForwardIterator first, ForwardIterator last,         Predicate pred);

из STL
Записан
Sergeich
Гость
« Ответ #2 : Июнь 07, 2007, 16:14 »

Код:
	QVariantList l;
...
QVariantList::iterator it = l.begin();
while ( it != l.end() ) {
if ( needRemove(*it) )
it = l.erase( it );
else
++it;
}
Записан
SABROG
Гость
« Ответ #3 : Июнь 07, 2007, 16:24 »

Alex Forth, спасибо за вектор.
Sergeich, была тоже мысль с увеличением указателя итератора.

Покурил Assistant, вот что нашел:

Код:

 QMutableListIterator<int> i(list);
 while (i.hasNext()) {
     int val = i.next();
     if (val < -32768 || val > 32767)
         i.remove();
 }
Записан
Tonal
Гость
« Ответ #4 : Июнь 07, 2007, 17:53 »

Код:

template<class Pred>
inline void remove(QVariantList& l, const Pred& needRemove) {
  l.erase(std::remove_if(l.begin(), l.end(), needRemove), l.end());
}
Записан
SABROG
Гость
« Ответ #5 : Июнь 07, 2007, 18:11 »

Tonal, ты бы хоть пояснил что за шаблончик такой интересный.
Я так понимаю это шаблон для встраиваемой функции remove, которой передается ссылка на лист и ссылка на объект любого типа, в котором содержится некоторое значение. Если это значение встречается в промежтке от begin до end, то на него возвращается итератор, который и уничтожается eraseом в промежутке от индекса найденного итератора до конца (end) ? Теперь глупый вопрос, этот код кросплатформенный ?

Я так понимаю этот код аналогичен этому (взято из Assistant'a):

Код:

int QList::removeAll ( const T & value )
Removes all occurrences of value in the list and returns the number of entries removed.
Example:
 QList<QString> list;
 list << "sun" << "cloud" << "sun" << "rain";
 list.removeAll("sun");
 // list: ["cloud", "rain"]
This function requires the value type to have an implementation of operator==().


Только это несколько не то, что мне надо. В листе все элементы уникальны. Мне надо брать каждый, делать запрос в базу или к другому массиву и сравнивать с ним, если есть пересечение, то удалять. Но в принципе я думаю справлюсь с этим, всего-лишь вручную увеличивая итератор после удаления, чтобы исключить пустые циклы.
Записан
Tonal
Гость
« Ответ #6 : Июнь 07, 2007, 19:30 »

Использовать элементарно.
Пишем функцию needRemove, который принимает параметр типа QVariant возвращает истину если его надо удалить.
Передаём её в remove вторым параметром. Первым лист над которым издеваемся. ;-)
Код:

bool needRemove(const QVariant& val) {
  // здесь выполняем твои запросы, и пересечения.
  //Возвращаем true если элемент нужно удалить
}


void doWork(QVariantList& list) {
  //Здесь происходит вызов needRemove для каждого элемента
  //списка, и те, для которых вернулось true удаляються
  remove(list, needRemove);
}
Записан
SABROG
Гость
« Ответ #7 : Июнь 07, 2007, 21:03 »

Пфф, что-то странное. Я думал, что в remove передается значение вторым параметром, а не ссылка на функцию, которая true возрващает ? Не будет ли так, что remove_if будет искать булевые значения true или false Улыбающийся ?
Записан
Tonal
Гость
« Ответ #8 : Июнь 08, 2007, 08:15 »

Нет. Ты перепутал с remove.
remove_if будет вызывать функцию для каждого значения, и по её результату решать что делать.

P.S. Почитай про STL - он всё таки часть языка, на котором ты пишешь. ;-)
Записан
SABROG
Гость
« Ответ #9 : Июнь 08, 2007, 09:48 »

Почитал http://www.sgi.com/tech/stl/

Эти "предикаты" меня в тупик ставят.

Код, порой, так усложняют, не понятно, что на самом деле происходит. Например свойства компонентов в delphi и bcb, думаешь, что записываешь в переменную, а на поверку оказывается, что вызываются функции типа setValue, getValue, где может быть все, что угодно, да еще перегрузка операторов. Все спотыкаюсь о камни подводные и спотыкаюсь. Об STL что-то маловато серьезных, русскоязычных, статей находится.
Записан
Tonal
Гость
« Ответ #10 : Июнь 09, 2007, 09:57 »

Возьми "Язык Программирования С++" 3 Страуструпа.
Очень понятно и доступно изложенно. ;-)

А насчёт усложнений - пиши на асемблере или на форте, только без макросов.
Как раз получается - что вижу то и произойдёт - этакое чукча-программирование. ;-)
Записан
SABROG
Гость
« Ответ #11 : Июнь 09, 2007, 11:42 »

Цитата: "Tonal"
Возьми "Язык Программирования С++" 3 Страуструпа.
Очень понятно и доступно изложенно. ;-)

А насчёт усложнений - пиши на асемблере или на форте, только без макросов.
Как раз получается - что вижу то и произойдёт - этакое чукча-программирование. ;-)


Ассемблер - первый язык который я выучил. Я на нем писал года 4, прошел дорогу от DOS'a с Turbo Assemblerом, плавно переходя с .com приложений до win16, потом пересел на MASM32 с туториалами IcZeilon'a, далее выбор был сделан в пользу Fasm32, пописал на нем утилиты различные типа тренеров, кряков и saveeditоров. Потом пересел на linux и снова пописал утилитки на fasm32 только уже используя GTK. Дальше решил понять что такое Perl, написал на нем IRC бота, который коннектился к MySQL базе и цеплял ответы на вопросы "Викторины", а потом уже пришел ко мне C++. И я вот уже года 2 пытаюсь в него въехать искренне не понимая, почему нельзя обойтись одними типами данных - бит, байт, байт*n

Эх хорошие были времена в Fido в конверенции RU.ASM, частенько решали задачки по оптимизации кода, как по скорости так и по размеру.
Записан
Страниц: [1]   Вверх
  Печать  
 
Перейти в:  


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