Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Remove Elements from an Unordered Map Fulfilling a Predicate

I want to remove elements (histogram bins) from an std::unordered_map (histogram) that fulfills a predictate (histogram bins having zero count) given as a lambda expression as follows

std::remove_if(begin(m_map), end(m_map), [](const Bin & bin) { return bin.second == 0; }); 

but GCC-4.6.1 complains as follows

/usr/include/c++/4.6/bits/stl_pair.h:156:2: error: assignment of read-only member ‘std::pair<const unsigned char, unsigned char>::first’ /usr/include/c++/4.6/bits/stl_pair.h: In member function ‘std::pair<_T1, _T2>& std::pair<_T1, _T2>::operator=(std::pair<_T1, _T2>&&) [with _T1 = const unsigned char, _T2 = long unsigned int, std::pair<_T1, _T2> = std::pair<const unsigned char, long unsigned int>]’: /usr/include/c++/4.6/bits/stl_algo.h:1149:13:   instantiated from ‘_FIter std::remove_if(_FIter, _FIter, _Predicate) [with _FIter = std::__detail::_Hashtable_iterator<std::pair<const unsigned char, long unsigned int>, false, false>, _Predicate = pnw::histogram<V, C, H>::pack() [with V = std::vector<unsigned char>, C = long unsigned int, H = std::unordered_map<unsigned char, long unsigned int, std::hash<unsigned char>, std::equal_to<unsigned char>, std::allocator<std::pair<const unsigned char, long unsigned int> > >]::<lambda(const Bin&)>]’ tests/../histogram.hpp:68:13:   instantiated from ‘void pnw::histogram<V, C, H>::pack() [with V = std::vector<unsigned char>, C = long unsigned int, H = std::unordered_map<unsigned char, long unsigned int, std::hash<unsigned char>, std::equal_to<unsigned char>, std::allocator<std::pair<const unsigned char, long unsigned int> > >]’ tests/../histogram.hpp:85:13:   instantiated from ‘void pnw::histogram<V, C, H>::normalize(uint) [with V = std::vector<unsigned char>, C = long unsigned int, H = std::unordered_map<unsigned char, long unsigned int, std::hash<unsigned char>, std::equal_to<unsigned char>, std::allocator<std::pair<const unsigned char, long unsigned int> > >, uint = unsigned int]’ tests/../histogram.hpp:121:51:   instantiated from ‘H& pnw::histogram<V, C, H>::add(It, It) [with It = __gnu_cxx::__normal_iterator<const unsigned char*, std::vector<unsigned char> >, V = std::vector<unsigned char>, C = long unsigned int, H = std::unordered_map<unsigned char, long unsigned int, std::hash<unsigned char>, std::equal_to<unsigned char>, std::allocator<std::pair<const unsigned char, long unsigned int> > >]’ tests/../histogram.hpp:129:55:   instantiated from ‘H& pnw::histogram<V, C, H>::add(const V&) [with V = std::vector<unsigned char>, C = long unsigned int, H = std::unordered_map<unsigned char, long unsigned int, std::hash<unsigned char>, std::equal_to<unsigned char>, std::allocator<std::pair<const unsigned char, long unsigned int> > >]’ tests/../histogram.hpp:57:60:   instantiated from ‘pnw::histogram<V, C, H>::histogram(const V&, pnw::histogram<V, C, H>::TYPE_t) [with V = std::vector<unsigned char>, C = long unsigned int, H = std::unordered_map<unsigned char, long unsigned int, std::hash<unsigned char>, std::equal_to<unsigned char>, std::allocator<std::pair<const unsigned char, long unsigned int> > >]’ tests/t_histogram.cpp:38:61:   instantiated from ‘void test_dense_histogram() [with T = unsigned char, C = long unsigned int]’ tests/t_histogram.cpp:64:5:   instantiated from ‘void test_histograms() [with C = long unsigned int]’ tests/t_histogram.cpp:200:29:   instantiated from here /usr/include/c++/4.6/bits/stl_pair.h:156:2: error: assignment of read-only member ‘std::pair<const unsigned char, long unsigned int>::first’ make: *** [tests/t_histogram.o] Error 1 

Isn't std::remove_if applicable to std::unordered_map?

like image 543
Nordlöw Avatar asked Feb 09 '12 11:02

Nordlöw


People also ask

How do you delete an unordered map value?

erasing by key: It takes a key as a parameter and erases the key and value. unordered_map. erase(const key); erase by range: It takes two iterators as a parameter and erases all the key and values present in between (including the starting iterator and excluding the end iterator).

How do you reset an unordered map?

C++ Unordered_map Library - clear() Function The C++ function std::unordered_map::clear() destroys the unordered_map by removing all elements and sets the size of unordered_map to zero.

Does unordered map preserve insertion order?

No. It's called "unordered" for a reason. If you need to maintain an order of insertion, you've chosen an unsuitable data structure.

What does unordered map return?

The unordered_map::count() returns one of the two values: True (1): If the specified key element is present in the unordered map, the function returns a value of 1 which can also be treated as a boolean true . It return 1 because the unordered map does not allow repetition of elements.


1 Answers

The answer is no (you can't use remove_if on associative containers). You need to do a simple loop; the erase(iterator) member now returns the next valid iterator - so your loop becomes:

for(auto it = begin(m_map); it != end(m_map);) {   if (it->second == 0)   {     it = m_map.erase(it); // previously this was something like m_map.erase(it++);   }   else     ++it; } 
like image 98
Nim Avatar answered Sep 26 '22 10:09

Nim