简体   繁体   中英

C++ Multimap manipulation

I have created a multimap as I have repeating keys. But I want do an efficient manipulation so that I can generate a new multimap with subsequent higher keys aligned. This is what I mean:

This is what I have:

key        values
11          qwer
11          mfiri
21          iernr
21          ghfnfjf
43          dnvfrf

This is what I want to achive

key        values
11          qwer,iernr
11          mfiri,iernr
21         iernr,dnvfrf
21          ghfnfjf,dnvfrf
43          dnvfrf

I have about 10 million entries so I am looking for something efficient.

In above value "qwer,iernr" is one string.

Here's a simple way to do it:

auto cur = map.begin();
auto next = map.upper_bound(cur->first);

for(; next != map.end(); next = map.upper_bound(cur->first))
{
    for(; cur != next; ++cur)
    {
        cur->second += ", ";
        cur->second += next->second;
    }
}

... given a std::multimap<int, std::string> map;

However, any operation transforming 10m+ elements isn't going to be super fast.

Looks like straight-forward way would work fine. Map elements will be laid out in ascending order (assuming compare operator suits you). So just going through the equal ranges and modifying them with value of the element just after the range will do what you want.

Clone map (if you need the original), take first element, get equal_range() for its key, modify values with value of second iterator in the range (unless it is the last one). Get equal_range() for the key of second iterator. Repeat.

agree with Eugene ! also see following reference in terms of equal_range() stl::multimap - how do i get groups of data?

To do this, you need to simply iterate through the map, while building the new map in order.

You can do this in two levels:

for (auto it=map.cbegin(); it != map.cend(); ) 
{ 
    // The inner loop is over all entries having the same key
    auto next_key_it=find_next_key_after(it);
    for (; it != next_key_it; ++it) {
         new_map.emplace_hint(new_map.end(), it->first, new_value(it->second, next_key_it));
    }
}

The new_value function (or lambda) does the value transformation (or not, if the second parameter is map.end()).

The find_next_key_after(it) function returns the same as map.upper_bound(it->first), but could also be implemented as linear search for the first entry with different key.

It depends on your (expected) key distribution, which to use - if keys repeat a small, limited number of times, linear search is better; if the number of different keys is limited, with large equal key ranges, then upper_bound may be better.

For guaranteed complexity, linear search is better: The whole algorithm then has O(n) complexity. Which is as efficient as you can get.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM