std :: multimap получает два диапазона - PullRequest
5 голосов
/ 07 сентября 2011

Я использую 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 ]

3 голосов
/ 07 сентября 2011

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

3 голосов
/ 07 сентября 2011

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

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

Редактировать: Я обдумывал это;легко просто изменить две петли в одну.

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;
    }
    ...
}
0 голосов
/ 07 сентября 2011

Если у вас есть доступ к 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! = key1.Проверка итераторов каждый раз в цикле имеет определенную стоимость.

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

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

...