Модераторы: bsa
  

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Проход контейнера с удалением. 
:(
    Опции темы
Mechatronic
Дата 29.7.2015, 10:06 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 73
Регистрация: 28.3.2010

Репутация: нет
Всего: нет



Здравствуйте. Есть список структур, который необходимо отфильтровать по одному из полей структуры по "правилу трех сигм".
Подскажите, пожалуйста, как это правильно делается?
Попробовал следующим образом - при некоторых наборах нормально удаляется, при некоторых вылетает.
Код

    List::iterator it = list.begin();
    for(; it != list.end();)
    {
        float delta = fabs((median - (*it).x));
        if(delta > 3 * standartDeviation)
        {
            List::iterator itToDel = it;
            it++;
            list.erase(itToDel);
        }else
        {
            it++;
        }
    }


List есть 
Код

typedef QList<MyStruct> List;


Спасибо.

Это сообщение отредактировал(а) Mechatronic - 29.7.2015, 10:06
PM MAIL   Вверх
rudolfninja
Дата 29.7.2015, 10:40 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 341
Регистрация: 19.2.2013
Где: г. Минск

Репутация: 1
Всего: 6



Доброе утро.
Наверное, тему надо было создавать в разделе про Qt.  У QList есть метод, removeAt(int index).
Получить индекс по итератору можно примерно так:
Код

int indx = it - list.begin();

С учетом всего, мной написанного, код будет таким:
Код


for(it = list.begin(); it != list.end(); it++)
{
        float delta = fabs((median - (*it).x));
        if(delta > 3 * standartDeviation)
        {
            int indx = it - list.begin();
            list.removeAt(indx);
        }
}


Это сообщение отредактировал(а) rudolfninja - 29.7.2015, 10:42
PM MAIL Skype   Вверх
Mechatronic
Дата 29.7.2015, 10:47 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 73
Регистрация: 28.3.2010

Репутация: нет
Всего: нет



rudolfninja, спасибо за ответ!
Но разве итератор останется валидным после удаления на тот момент, когда мы его начнем инкрементировать?
Так же очень интересует решение для STL - в проекте пара модулей, где используются STL контейнеры - там в таких случаях просто делается it = list.begin() без инкремента, что как-то не хорошо.
PM MAIL   Вверх
Sartorius
Дата 29.7.2015, 11:02 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1568
Регистрация: 18.7.2006
Где: Ivory tower

Репутация: 2
Всего: 37



В таких случаях обычно обходят копию контейнера в цикле с удалением объектов в оригинальном контейнере. Можно еще отложить удаление - сначала составить список объектов, которые нужно исключить, а потом их убрать из контейнера.
PM MAIL ICQ   Вверх
rudolfninja
Дата 29.7.2015, 11:06 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 341
Регистрация: 19.2.2013
Где: г. Минск

Репутация: 1
Всего: 6



Цитата(Mechatronic @  29.7.2015,  10:47 Найти цитируемый пост)
Но разве итератор останется валидным после удаления на тот момент, когда мы его начнем инкрементировать?

Хороший вопрос.
Вообще, как решение, можно проходит список по индексам и удалять элемент по индексу.
Если надо использование итераторов, тогда можно такое решение:
Код

List::iterator current_it = list.begin();
List::iterator end_it = list.end();

while(current_it != end_it)
{
    float delta = fabs((median - (*current_it ).x));
    if(delta > 3 * standartDeviation)
    {
        list.erase(current_it ++);
        end_it = list.end();
    }
    else
        current_it++;
}

Это должно работать и для std-списка и для QList.

Хотя, я не уверен, что с использованием итераторов производительность возрастет в разы, по сравнению с использованием индексов.
PM MAIL Skype   Вверх
Mechatronic
Дата 29.7.2015, 11:08 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 73
Регистрация: 28.3.2010

Репутация: нет
Всего: нет



Sartorius, спасибо за ответ! Такой вариант представлял, но думал, что так никто не делает.
А если обходим map - то же самое? Там ведь большие затраты на то, чтобы положить элемент, чем в  list.

Добавлено через 4 минуты и 25 секунд
rudolfninja, по-моему ваш крайние код от моего изначального существенно не отличается . 
Вы просто сохранили конечный итератор при удалении, а у меня он каждый цикл брался из списка.
Разве нет?
PM MAIL   Вверх
Sartorius
Дата 29.7.2015, 11:25 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1568
Регистрация: 18.7.2006
Где: Ivory tower

Репутация: 2
Всего: 37



Цитата(Mechatronic @ 29.7.2015,  12:08)
А если обходим map - то же самое? Там ведь большие затраты на то, чтобы положить элемент, чем в  list.

"положить элемент" - имеется ввиду при создании копии? std::map::operator= создает копию, думаю, достаточно эффективно. Но для большого map-а наверно лучше подойдет сохранение ключей, которые должны быть удалены, в списке с удалением после обхода map-а.
PM MAIL ICQ   Вверх
rudolfninja
Дата 29.7.2015, 11:31 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 341
Регистрация: 19.2.2013
Где: г. Минск

Репутация: 1
Всего: 6



Да, по сути, получается тоже самое, но у меня такой удаление такого списка нормально отработало.
PM MAIL Skype   Вверх
Mechatronic
Дата 29.7.2015, 12:12 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 73
Регистрация: 28.3.2010

Репутация: нет
Всего: нет



Sartorius, имеется в виду map::insert. Он же тогда бежит по ветвям дерева и сравнивает, а в листе просто соединяет два указателя.
rudolfninja, у меня, к сожалению, падает на этом месте. Похоже, вам просто повезло с набором данных smile
PM MAIL   Вверх
rudolfninja
Дата 29.7.2015, 12:14 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 341
Регистрация: 19.2.2013
Где: г. Минск

Репутация: 1
Всего: 6



А при каком наборе у вас падает? Возможно, при удалении последнего элемента?
PM MAIL Skype   Вверх
Mechatronic
Дата 29.7.2015, 12:25 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 73
Регистрация: 28.3.2010

Репутация: нет
Всего: нет



Список на много тысяч позиций совсем не хочется копировать ...
rudolfninja, да, вы правы - при удалении последнего. Тогда вместо инкремента, просто присваиваем it = list.end(). логично?
Так, вроде, не падает.
Код

    List::iterator it = list.begin();
    for(; it != list.end();)
    {
        float delta = fabs((median - (*it).x));
        if(delta > 3 * standartDeviation)
        {
            List::iterator itToDel = it;
            if( it != (list.end() - 1))
            {
                it++;
                list.erase(itToDel);
            }else
            {
                list.erase(itToDel);
                it = list.end();
            }
        }else
        {
            it++;
        }
    }

PM MAIL   Вверх
baldina
Дата 29.7.2015, 17:18 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 3433
Регистрация: 5.12.2007
Где: Москва

Репутация: 15
Всего: 101



в STL std::list::remove_if()

Код

list.remove_if([&](auto el){
  return fabs(median - el.x) > 3*standartDeviation;
});


Добавлено через 3 минуты и 40 секунд
Цитата(rudolfninja @  29.7.2015,  10:40 Найти цитируемый пост)
У QList есть метод, removeAt

есть class QMutableListIterator у которого есть метод remove
PM MAIL   Вверх
  
Ответ в темуСоздание новой темы Создание опроса
Правила форума "C/C++: Для новичков"
JackYF
bsa

Запрещается!

1. Публиковать ссылки на вскрытые компоненты

2. Обсуждать взлом компонентов и делиться вскрытыми компонентами

  • Действия модераторов можно обсудить здесь
  • С просьбами о написании курсовой, реферата и т.п. обращаться сюда
  • Вопросы по реализации алгоритмов рассматриваются здесь


Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, JackYF, bsa.

 
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | C/C++: Для новичков | Следующая тема »


 




[ Время генерации скрипта: 0.0992 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.