как с помощью STL удалить некоторые элементы
От: Socket Ниоткуда http://www.samborsky.com
Дата: 10.08.07 17:24
Оценка:
Есть контейнер, который содержит в себе классы.

class UrlContainer {
public:
    string url;
    string parent;
    bool used;
};

class UrlContainerSortCriterion {
public:
    bool operator() (const UrlContainer& u1, const UrlContainer& u2) const {
        return u1.url < u2.url;
    }
};

typedef set<UrlContainer,UrlContainerSortCriterion> UrlContainerSet;

class CUrlContainer {
public:

    CUrlContainer();
    ~CUrlContainer();
private:
    UrlContainerSet m_set;

protected:
};



Как с помощью алгоритмов удалить все элементы моего контера, которые содержат отределенный parent
понимаю что нужно использовать remove_if, но если можете — подскажите, как должна выглядить процедура
сравнения
http://www.samborsky.com — мой блог
Re: как с помощью STL удалить некоторые элементы
От: np9mi7 Россия  
Дата: 10.08.07 17:38
Оценка:
Здравствуйте, Socket, Вы писали:

S>Как с помощью алгоритмов удалить все элементы моего контера, которые содержат отределенный parent

S>понимаю что нужно использовать remove_if, но если можете — подскажите, как должна выглядить процедура

remove_if не катит — итератор не той категории, а вот линейно пройти и вызвать std::set<...>::erase(const key_type& _Key); это то что тебе нужно.
[RSDN@Home 1.1.4 stable SR1 rev. 568 on Windows 2003 5.2.3790.0]
"В любое мгновение принятия решения, лучшее, что вы можете сделать, это принять правильное решение; следующим лучшим вариантом будет принять неправильное решение, худший вариант – не принимать решения совсем" (c) Теодор Рузвельт.
Re: как с помощью STL удалить некоторые элементы
От: Socket Ниоткуда http://www.samborsky.com
Дата: 10.08.07 17:45
Оценка:
>remove_if не катит — итератор не той категории
как это не с той категории? почему нельзя применять алгоритмы к таким итераторам?

p.s. так и делаю сейчас — удаляю полным перебором, но понимаю что это не верно, тоесть работет , но догадываюссь что можно сделать одной строкой,
к тому же навярняка с алгоритмом быстрее.
http://www.samborsky.com — мой блог
Re: как с помощью STL удалить некоторые элементы
От: Sashaka Россия  
Дата: 10.08.07 17:50
Оценка:
S> bool operator() (const UrlContainer& u1, const UrlContainer& u2) const {
S> return u1.url < u2.url;
S> }
S>};

S>typedef set<UrlContainer,UrlContainerSortCriterion> UrlContainerSet;


S>class CUrlContainer {

S>public:

S> CUrlContainer();

S> ~CUrlContainer();
S>private:
S> UrlContainerSet m_set;

S>protected:

S>};

S>[/ccode]



S>Как с помощью алгоритмов удалить все элементы моего контера, которые содержат отределенный parent

S>понимаю что нужно использовать remove_if, но если можете — подскажите, как должна выглядить процедура
S>сравнения

struct MyRem
{
   MyRem(int some_param)
     : m_some_param(some_param)
   {}
   bool operator()(const CUrlContainer& obj)
   {
     if (... && ...) //в проверках юзаем some_param, если надо
       return true;
     return false;
   }
   private:
      int m_some_param
}

MyVec vec;
//... заполняем
MyVec::iterator new_last = remove_if(vec.begin(),vec.end(),MyRem(100));
vec.erase(new_last, vec.end());
Re[2]: как с помощью STL удалить некоторые элементы
От: Awaken Украина  
Дата: 10.08.07 18:18
Оценка:
Здравствуйте, Sashaka, Вы писали:

S>
S>struct MyRem
S>{
S>   MyRem(int some_param)
S>     : m_some_param(some_param)
S>   {}
S>   bool operator()(const CUrlContainer& obj)
S>   {
S>     if (... && ...) //в проверках юзаем some_param, если надо
S>       return true;
S>     return false;
S>   }
S>   private:
S>      int m_some_param
S>}


тогда уж вот так:

template <typename _V> 
struct EqualToVal : std::binary_function<CUrlContainer, _V, bool>
{
   bool operator()(const CUrlContainer& arg1, const _V& arg2) const
   {
      return arg1.parent == arg2;
   }
};
Re[2]: как с помощью STL удалить некоторые элементы
От: sc Россия  
Дата: 10.08.07 18:21
Оценка:
Здравствуйте, Sashaka, Вы писали:

S>
<skipped>
S>MyVec vec;
S>//... заполняем
S>MyVec::iterator new_last = remove_if(vec.begin(),vec.end(),MyRem(100));
S>vec.erase(new_last, vec.end());
S>


так у него set а не вектор, поэтому наверное и проблема.
Re[3]: как с помощью STL удалить некоторые элементы
От: sc Россия  
Дата: 10.08.07 18:36
Оценка:
Здравствуйте, sc, Вы писали:

sc>Здравствуйте, Sashaka, Вы писали:


S>>
<skipped>
S>>MyVec vec;
S>>//... заполняем
S>>MyVec::iterator new_last = remove_if(vec.begin(),vec.end(),MyRem(100));
S>>vec.erase(new_last, vec.end());
S>>


sc>так у него set а не вектор, поэтому наверное и проблема.

хотя нет, все работает и с set
Re: как с помощью STL удалить некоторые элементы
От: NikeByNike Россия  
Дата: 10.08.07 19:05
Оценка:
Здравствуйте, Socket, Вы писали:

S>Как с помощью алгоритмов удалить все элементы моего контера, которые содержат отределенный parent

S>понимаю что нужно использовать remove_if, но если можете — подскажите, как должна выглядить процедура
S>сравнения

remove не удаляет элементы, а перемещает их в конец.
Т.е. удаление с его помощью выглядит так:
cont.erase(remove_if(cont.begin(), cont.end(), pred), cont.end());
Нужно разобрать угил.
Re[4]: как с помощью STL удалить некоторые элементы
От: Awaken Украина  
Дата: 10.08.07 19:24
Оценка:
sc>>так у него set а не вектор, поэтому наверное и проблема.
sc>хотя нет, все работает и с set

это компилится на VC++ 8.0, но в общем случае не будет, например в SGI и gcc.
в sgi итераторы в set/multiset константны , а мутирующие алгоритмы требуют наличия mutable итератора
см.книгу Мейерса про эффективное использование STL, там подробно описано почему нельзя так делать
Re[3]: как с помощью STL удалить некоторые элементы
От: Sashaka Россия  
Дата: 10.08.07 19:29
Оценка:
A>тогда уж вот так:

A>
A>template <typename _V> 
A>struct EqualToVal : std::binary_function<CUrlContainer, _V, bool>
A>{
A>   bool operator()(const CUrlContainer& arg1, const _V& arg2) const
A>   {
A>      return arg1.parent == arg2;
A>   }
A>};
A>


для remove_if разве не предикат исп-ся? или юзать через bind2nd?

у меня пара вопросов:
1) чем это лучше ?
2) зачем наследоваться от std::binary_function ?
3) пример использования этого варианта? имхо он будет сложнее:
   remove_if(v.begin(), v.end(), bind2nd(EqualToVal<string>(),param) );

вместо:
   remove_if(v.begin(), v.end(), EqualToVal(param));

Или это правильней с т.зр. использования STL? А может объект функции перестает таким быть при добавлении конструктора?

Я в книжках встречал и 1 вариант и второй (второй по большей части со встроенными в STL объектами функций)
Re[4]: как с помощью STL удалить некоторые элементы
От: Awaken Украина  
Дата: 10.08.07 19:55
Оценка:
S>для remove_if разве не предикат исп-ся? или юзать через bind2nd?
через бинд

S>1) чем это лучше ?

здесь не нужен функтор с состоянием, излишество имхо.

S>2) зачем наследоваться от std::binary_function ?

это делает функтор адаптируемым. например можно написать std::not1(EqualToVal) и т.д.
можно и от unary_function
Re: как с помощью STL удалить некоторые элементы
От: Bell Россия  
Дата: 13.08.07 07:15
Оценка:
Здравствуйте, Socket, Вы писали:

S>Как с помощью алгоритмов удалить все элементы моего контера, которые содержат отределенный parent

S>понимаю что нужно использовать remove_if, но если можете — подскажите, как должна выглядить процедура
S>сравнения

remove_if в данном случае не подойдет. За подробностями можно обратиться в поиск — эта тема обсуждалась не раз.
Так что вариант с "ручным проходом" и удалением, ИМХО, оптимален.
Но если хочется непременно воспользоваться алгоритмом, то можно предложить remove_copy_if:

class parent_cmp
{
   string parent_;
public:
   parent_cmp(const string& parent) : parent_(parent) {}

   bool operator()(const UrlContainer& obj) const
   {
      return parent_ != obj.parent;
   }
};

int main(int argc, char* argv[])
{
   UrlContainerSet s1;
   UrlContainer c;
   c.url = "1";
   c.parent = "1";
   s1.insert(c);
   c.url = "2";
   c.parent = "2";
   s1.insert(c);

   UrlContainerSet tmp;
   remove_copy_if(s1.begin(), s1.end(), inserter(tmp, tmp.begin()), parent_cmp("2"));
   s1.swap(tmp);

   return 0;
}


ЗЫ
Тема прохода с удалением по set/map тоже частенько всплывает, т.к. тут есть подводные камни. На всякий случай посмотри в поиске и эту тему, или приведи свой код для экспертизы
Любите книгу — источник знаний (с) М.Горький
Re[2]: как с помощью STL удалить некоторые элементы
От: Кодт Россия  
Дата: 13.08.07 09:18
Оценка:
Здравствуйте, Socket, Вы писали:

>>remove_if не катит — итератор не той категории

S>как это не с той категории? почему нельзя применять алгоритмы к таким итераторам?

Потому что у set и map нельзя выполнять присваивания элементов целиком (ключи — константы).
А remove_if делает именно это.
template<class It, class Pred>
It remove_if(It begin, It end, Pred pred)
{
    It passed, testing;
    // [begin,passed) - то, что прошло проверку
    // [passed,testing) - буферная зона
    // по окончании [begin,passed) - хорошие, [passed,end) - на выброс
    
    for(passed=testing=begin; testing!=end; ++testing)
    {
        if(!pred(*testing))
        {
            if(passed!=testing) *passed = *testing;
            ++passed;
        }
    }
    return passed;
}


В случае set нужно бегать и выборочно удалять элементы. Кстати, это же относится и к list.
... << RSDN@Home 1.2.0 alpha rev. 655>>
Перекуём баги на фичи!
Re[2]: как с помощью STL удалить некоторые элементы
От: Кодт Россия  
Дата: 13.08.07 09:18
Оценка: 8 (1)
Здравствуйте, NikeByNike, Вы писали:

NBN>remove не удаляет элементы, а перемещает их в конец.


remove затирает удаляемые элементы, и вовсе не обязано куда-то их перемещать.
Интервал [result_of_remove, end) — "свободная" память, содержащая валидные, но произвольные значения (копии передвинутых или удалённых элементов).
... << RSDN@Home 1.2.0 alpha rev. 655>>
Перекуём баги на фичи!
Re: как с помощью STL удалить некоторые элементы
От: Socket Ниоткуда http://www.samborsky.com
Дата: 21.08.07 14:09
Оценка:
Почему не компилируется ?
Студия 7.1

template <typename _V> 
struct EqualToVal : std::binary_function<CUrlContainer, _V, bool>{
    bool operator()(const CUrlContainer& arg1, const _V& arg2) const{
        return arg1.parent == arg2;
    }
};

void CUrlContainer::delete_by_parent(const string& parent){

    if( lock.Lock() ){

        m_set.erase(remove_if(m_set.begin(), m_set.end(), bind2nd(EqualToVal<string>(),parent) ));

        lock.Unlock();
    }

}


c:\Program Files\Microsoft Visual Studio .NET 2003\Vc7\include\algorithm(64): error C2664: 'std::binder2nd<_Fn2>::result_type std::binder2nd<_Fn2>::operator ()(std::binder2nd<_Fn2>::argument_type &) const' : cannot convert parameter 1 from 'std::allocator<_Ty>::value_type' to 'std::binder2nd<_Fn2>::argument_type &'
with
[
_Fn2=EqualToVal<std::string>
]
and
[
_Ty=UrlContainer
]
and
[
_Fn2=EqualToVal<std::string>
]
c:\Program Files\Microsoft Visual Studio .NET 2003\Vc7\include\algorithm(491): error C2664: 'std::binder2nd<_Fn2>::result_type std::binder2nd<_Fn2>::operator ()(std::binder2nd<_Fn2>::argument_type &) const' : cannot convert parameter 1 from 'std::allocator<_Ty>::value_type' to 'std::binder2nd<_Fn2>::argument_type &'
with
[
_Fn2=EqualToVal<std::string>
]
and
[
_Ty=UrlContainer
]
and
[
_Fn2=EqualToVal<std::string>
]
http://www.samborsky.com — мой блог
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.