Q: remove_if и map?
От: pesticide Украина  
Дата: 29.07.02 20:34
Оценка:
Хайолл!

Есть словарь, отображающий, допустим, некоторое число на некоторую структуру: map<ROW_KEY, CRowFromat*>.
Надо пройти по всем элементам словаря и удалить те из них, у которых в структуре некоторе поле будет установлено в определенное значение. Я применил следующий код:

std::map<ROW_KEY, CRowFromat*>::reverse_iterator pIter;
for(pIter = m_Rows.rbegin(); pIter != m_Rows.rend(); pIter--)
{
CRowFromat *rf = pIter->second;
if(rf->field == 7)
{
m_Rows.erase(pIter->first);
}
}

reverse_iterator пришлось применить так как тот же код с прямым итератором вызывал ошибку в erase(pIter->first)

Вопрос можно ли как-то к map применить алгоритм remove_if, чтобы не морочить себе голову с циклом? в MSDN-е есть пример только для list, а вот что передается в функцию-предикат в случае словаря?
Очень хотелось бы посмотреть на код.

Вопрос чисто из любопытства и в позновательных целях поэтому интересует именно возможность применения к map алгоритма remove_if или любого другого stl-алгоритма, реализующего такую функцию, хотя, по-моему, других таких нет.

Заранее благодарен

Удачи
Re: Q: remove_if и map?
От: Аноним  
Дата: 30.07.02 06:48
Оценка:
Здравствуйте pesticide, Вы писали:

P>std::map<ROW_KEY, CRowFromat*>::reverse_iterator pIter;

P>for(pIter = m_Rows.rbegin(); pIter != m_Rows.rend(); pIter--)
P>{
P> CRowFromat *rf = pIter->second;
P> if(rf->field == 7)
P> {
P> m_Rows.erase(pIter->first);
P> }
P>}


прямой итератор:

std::map<ROW_KEY, CRowFromat*>::iterator pIter;
for(pIter = m_Rows.begin(); pIter != m_Rows.end(); )
{
    CRowFromat *rf = pIter->second;
    if(rf->field == 7)
    {
        m_Rows.erase(pIter++);
    }
    else ++pIter;
}


итерация должна происходить в самом цикле, а не в третьем поле for.
Re: Q: remove_if и map?
От: Flamer Кипр http://users.livejournal.com/_flamer_/
Дата: 30.07.02 06:51
Оценка:
Здравствуйте pesticide, Вы писали:

P>Хайолл!


P>Есть словарь, отображающий, допустим, некоторое число на некоторую структуру: map<ROW_KEY, CRowFromat*>.

P>Надо пройти по всем элементам словаря и удалить те из них, у которых в структуре некоторе поле будет установлено в определенное значение. Я применил следующий код:

P>std::map<ROW_KEY, CRowFromat*>::reverse_iterator pIter;

P>for(pIter = m_Rows.rbegin(); pIter != m_Rows.rend(); pIter--)
P>{
P> CRowFromat *rf = pIter->second;
P> if(rf->field == 7)
P> {
P> m_Rows.erase(pIter->first);
P> }
P>}

P>reverse_iterator пришлось применить так как тот же код с прямым итератором вызывал ошибку в erase(pIter->first)


P>Вопрос можно ли как-то к map применить алгоритм remove_if, чтобы не морочить себе голову с циклом? в MSDN-е есть пример только для list, а вот что передается в функцию-предикат в случае словаря?

P>Очень хотелось бы посмотреть на код.

P>Вопрос чисто из любопытства и в позновательных целях поэтому интересует именно возможность применения к map алгоритма remove_if или любого другого stl-алгоритма, реализующего такую функцию, хотя, по-моему, других таких нет.


P>Заранее благодарен


P>Удачи




Может, не совсем то, но вот здесь
Автор: DarkGray
Дата: 23.07.02
обсуждалась близкая тема.
Re: Q: remove_if и map?
От: Bell Россия  
Дата: 30.07.02 07:49
Оценка:
Здравствуйте pesticide, Вы писали:

P>Вопрос можно ли как-то к map применить алгоритм remove_if, чтобы не морочить себе голову с циклом? в MSDN-е есть пример только для list, а вот что передается в функцию-предикат в случае словаря?

P>Очень хотелось бы посмотреть на код.

P>Вопрос чисто из любопытства и в позновательных целях поэтому интересует именно возможность применения к map алгоритма remove_if или любого другого stl-алгоритма, реализующего такую функцию, хотя, по-моему, других таких нет.


P>Заранее благодарен


К std::map, а равно и к другим ассоциативным контейнерам алгоритм remove_if применить нельзя. Ведь remove_if использует прямое присваивание одного элемента контейнера другому, импользуя forward_iterator, а это противоречит природе ассоциативных контейнеров (ну вернее не сам использует это присваивание, а вызывает remove_copy_if, в которой и происходит такое присваивание).
А вообще просто посмотри код этих двух функций — там все тривиально и сразу понятно.

А то, что тебе нужно, можно организовать так (только понадобиться дополнительный map):

using namespace std;

typedef map<int, int> MyMap;

class MyPred
{
   int _nCmpValue;
public:
   MyPred(int nValue) : _nCmpValue(nValue) {}
   bool operator () (const MyMap::value_type& arg) 
   { 
      if(arg.second == _nCmpValue) 
         return true; 
      return false;
   }
};

int main(void)
{
   MyMap aMap;
   aMap[0] = 0;
   aMap[1] = 0;
   aMap[2] = 0;
   aMap[3] = 1;
   MyMap aMap2;

   remove_copy_if(aMap.begin(), aMap.end(), inserter(aMap2, aMap2.begin()), MyPred(0));

   for(MyMap::iterator it = aMap2.begin(); it != aMap2.end(); ++it)
      cerr << it->first << " " << it->second << endl;
   
   return 0;
}



вывод: 3 1
Любите книгу — источник знаний (с) М.Горький
Re: Q: remove_if и map?
От: DarkGray Россия http://blog.metatech.ru/post/ogni-razrabotki.aspx
Дата: 30.07.02 08:18
Оценка: 5 (1)
Здравствуйте pesticide, Вы писали:

P>Вопрос можно ли как-то к map применить алгоритм remove_if, чтобы не морочить себе голову с циклом? в MSDN-е есть пример только для list, а вот что передается в функцию-предикат в случае словаря?

P>Очень хотелось бы посмотреть на код.

remove_if применить для map не получится, т.к. remove_if из stl вместо того чтобы просто удалять элементы, копирует поздние элементы на место предыдущих удаленных (что может быть хорошо для vector-а, но совсем не подходит для остальных коллекций list, map, set)


Предикат для map пишется так:
typedef std::map<ROW_KEY, CRowFormat*> Map;

bool Func (const Map::value_type &v)
{
  return v.second->field == 7;
}



remove_if для коллекций отличных от vector пишется так:
namespace std
{
  template<class Collection, class Predicat>
  void remove_if2 (Collection &doc, Collection::iterator it1, Collection::iterator it2, Predicat pr)
  {
    for (Collection::iterator it = it1, nit; it != it2;)
    {
      nit = it; ++nit;
      if (pr(*it))
        doc.erase (it);
    }
  }
  template<class Collection, class Predicat>
  inline void remove_if2 (Collection &doc, Predicat pr)
  {
    remove_if2 (doc, doc.begin(), doc.end(), pr);
  }
};

void main()
{
  Map m;
  std::remove_if2 (m, m.begin(), m.end(), Func);
}
Re[2]: Q: remove_if и map?
От: Андрей Тарасевич Беларусь  
Дата: 30.07.02 08:27
Оценка:
Здравствуйте DarkGray, Вы писали:

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


P>>Вопрос можно ли как-то к map применить алгоритм remove_if, чтобы не морочить себе голову с циклом? в MSDN-е есть пример только для list, а вот что передается в функцию-предикат в случае словаря?

P>>Очень хотелось бы посмотреть на код.

DG>remove_if применить для map не получится, т.к. remove_if из stl вместо того чтобы просто удалять элементы, копирует поздние элементы на место предыдущих удаленных (что может быть хорошо для vector-а, но совсем не подходит для остальных коллекций list, map, set)


Почему не подходит? От такого 'remove_if' до 'remove_if' с удалением — один шаг. Если у нас есть предикат 'pr' и map 'm', то сделать удаление можно так:

m.erase(std::remove_if(m.begin(), m.end(), pr), m.end());
Best regards,
Андрей Тарасевич
Re[3]: Q: remove_if и map?
От: DarkGray Россия http://blog.metatech.ru/post/ogni-razrabotki.aspx
Дата: 30.07.02 08:35
Оценка:
Здравствуйте Андрей Тарасевич, Вы писали:

АТ>Почему не подходит? От такого 'remove_if' до 'remove_if' с удалением — один шаг. Если у нас есть предикат 'pr' и map 'm', то сделать удаление можно так:


АТ>
АТ>m.erase(std::remove_if(m.begin(), m.end(), pr), m.end());
АТ>


Потому, что многие коллекции не поддерживают копирования полных элементов, в частности, map.

Во вторых, даже если копирование елементов поддерживается, как например в list, то выше приведенный алгоритм будет не оптимален, по сравнению с моим вариантом.
Re[4]: Q: remove_if и map?
От: Андрей Тарасевич Беларусь  
Дата: 30.07.02 15:29
Оценка:
Здравствуйте DarkGray, Вы писали:

DG>Здравствуйте Андрей Тарасевич, Вы писали:


АТ>>Почему не подходит? От такого 'remove_if' до 'remove_if' с удалением — один шаг. Если у нас есть предикат 'pr' и map 'm', то сделать удаление можно так:


АТ>>
АТ>>m.erase(std::remove_if(m.begin(), m.end(), pr), m.end());
АТ>>


DG>Потому, что многие коллекции не поддерживают копирования полных элементов, в частности, map.


Хм... Логично.

DG>Во вторых, даже если копирование елементов поддерживается, как например в list, то выше приведенный алгоритм будет не оптимален, по сравнению с моим вариантом.


Ну это уже, как говорится, whom how.
Best regards,
Андрей Тарасевич
Re[2]: Q: remove_if и map?
От: KA it-knowledge-base.blogspot.com
Дата: 03.07.04 10:57
Оценка:
Здравствуйте, DarkGray, Вы писали:

[...]

DG>remove_if для коллекций отличных от vector пишется так:

DG>
DG>namespace std
DG>{
DG>  template<class Collection, class Predicat>
DG>  void remove_if2 (Collection &doc, Collection::iterator it1, Collection::iterator it2, Predicat pr)
DG>  {
DG>    for (Collection::iterator it = it1, nit; it != it2; it = nit)
DG>    {
DG>      nit = it; ++nit;
DG>      if (pr(*it))
DG>        doc.erase (it);
DG>    }
DG>  }
DG>};

[...]

DG>


Исправление выделено жирным шрифтом.
Хотя, думаю, все и так догадались ...
//
#import <windows.bas>
class IWindows9x:protected DOS { private: virtual HANDLE EnumClouds()=0; };
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.