5

我正在使用 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)
{
    ...
}
4

3 回答 3

3

您开始使用的代码是最直接的。

如果你真的想在同一个循环中迭代两个范围,你可以创建一个自定义迭代器,它接受两个迭代器范围,迭代第一个直到它完成然后切换到第二个。这可能比它的价值更麻烦,因为您需要自己实现所有迭代器成员。

编辑:我想太多了;只需将两个循环修改为一个循环即可。

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;
    }
    ...
}
于 2011-09-07T15:27:06.580 回答
3

当然,Boost 会这样做。使用 Boost.Range 和它的join功能会让你得到你想要的。有关更多详细信息,请参阅Boost Range Library: Traversing Two Ranges Sequentially

于 2011-09-07T15:29:56.080 回答
0

如果您可以访问 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 插入到一个集合中,所以你只得到一个副本?

一些实验可能是有序的。不要忘记将您的第一个猜测加入其中。就速度而言,它可能会让您感到惊讶。除非范围通常很长和/或循环操作很昂贵,否则可能不值得为额外的簿记而头疼。

于 2011-09-07T19:38:57.203 回答