std:: multimap получение двух диапазонов


Я использую C++ std::multimap, и мне приходится перебирать два разных ключа. Есть ли эффективный способ сделать это, кроме создания двух диапазонов и циклического перебора этих диапазонов отдельно?

Вот как я делаю это сейчас:

std::pair<std::multimap<String, Object*>::iterator,std::multimap<String, Object*>::iterator> range;
std::pair<std::multimap<String, Object*>::iterator,std::multimap<String, Object*>::iterator> range2;

// get the range of String key
range = multimap.equal_range(key1);
range2 = multimap.equal_range(key2);

for (std::multimap<String, Object*>::iterator it = range.first; it != range.second; ++it)
{
    ...
}
for (std::multimap<String, Object*>::iterator it2 = range2.first; it2 != range2.second; ++it2)
{
    ...
}
3 5

3 ответа:

Код, с которого вы начали, самый простой.

Если вы действительно хотите перебирать два диапазона в одном цикле, вы можете создать пользовательский итератор, который берет два диапазона итератора, перебирает первый, пока это не будет сделано, а затем переключается на второй. Это, вероятно, больше проблем, чем стоит, так как вам нужно будет реализовать все члены итератора самостоятельно.

Edit: я слишком много думал об этом; легко просто изменить два цикла в один один.

for (std::multimap<String, Object*>::iterator it = range.first; it != range2.second; ++it)
{
    if (it == range.second)
    {
        it = range2.first;
        if (it == range2.second)
            break;
    }
    ...
}

Boost делает это, конечно. Использование Boost.Диапазон и его функция join дадут вам то, что вы хотите. Дополнительную информацию смотрите в разделе Boost Range Library: последовательное прохождение двух диапазонов.

Если у вас есть доступ к C++-11 (Visual Studio 10+, gcc-4.5+) и Вам разрешено его использовать auto - это настоящая жемчужина:

// get the range of String key
auto range = multimap.equal_range(key1);
auto range2 = multimap.equal_range(key2);

for (auto it = range.first; it != range.second; ++it)
{
    ...
}
for (auto it2 = range2.first; it2 != range2.second; ++it2)
{
    ...
}

В любом случае, я бы просто проверил ключи и сделал только второй цикл, если key2 != ключ1. Проверка итераторов каждый раз в цикле имеет некоторую стоимость.

Std:: set_difference первого диапазона от второго может упростить код. Может быть, std:: set_union два диапазона и вставить через back_inserter в набор, так что вы получите только одну копию?

Некоторые эксперименты могут быть в порядке. Не забудьте поставить свою первую догадку в смесь. Это может удивить вас, будучи просто прекрасным с точки зрения скорости. Если диапазоны, как правило, очень длинные и / или операция цикла не является дорогостоящей, это может не стоить головной боли дополнительной бухгалтерии.