I have code that looks essentially like this:
我的代码看起来基本上是这样的:
std::map<int, int> map1, map2;
BOOST_FOREACH(int i, map1)
{
// do steps 1-5 here...
}
BOOST_FOREACH(int i, map2)
{
// do steps 1-5 (identical to above) here...
}
Is there any way to concatenate the maps to eliminate the duplicate code in the second loop? Or a way to extend BOOST_FOREACH to iterate over two different maps in one go? Obviously I don't want to increase the time complexity of the program (otherwise I could just create a new map and insert into it map1 and map2). I have a feeling I am missing something rudimentary here.
有没有办法连接映射以消除第二个循环中的重复代码?或者一种方法来扩展BOOST_FOREACH以一次迭代两个不同的地图?显然我不想增加程序的时间复杂度(否则我可以创建一个新的map并插入map1和map2)。我有一种感觉,我在这里遗漏了一些不成熟的东西。
6 个解决方案
#1
You could define a function:
你可以定义一个函数:
typedef std::map<int, int> IntMap;
void doStuffWithInt(IntMap::value_type &i)
{
// steps 1 to 5
}
BOOST_FOREACH(IntMap::value_type &i, map1)
doStuffWithInt(i);
BOOST_FOREACH(IntMap::value_type &i, map2)
doStuffWithInt(i);
Although in that case it might be even simpler to use std::for_each
:
虽然在这种情况下使用std :: for_each可能更简单:
for_each(map1.begin(), map1.end(), doStuffWithInt);
for_each(map2.begin(), map2.end(), doStuffWithInt);
#2
The idea here is to write a special type of iterators to virtually merge two containers, as far as BOOST_FOREACH is concerned. Note that i am not creating a new container out of the two existing ones. I am simply jumping from the first container's end() to the second container's begin() iterator. I did not try and write the actual merged_iterator class, but although it might a bit long to write, it's not technically difficult. I am actually surprised not to have found something like that using google. I did not look for long, though !
这里的想法是编写一种特殊类型的迭代器来虚拟地合并两个容器,就BOOST_FOREACH而言。请注意,我不是从现有的两个容器中创建一个新容器。我只是从第一个容器的end()跳转到第二个容器的begin()迭代器。我没有尝试编写实际的merged_iterator类,但是虽然编写起来可能有点长,但这在技术上并不困难。我真的很惊讶没有使用谷歌找到类似的东西。不过我看起来并不长久!
template<typename Container>
boost::iterator_range<
merged_iterator<Container::iterator>
>
concat_containers( Container& c1, Container& c2 )
{
typedef merged_iterator<typename Container::iterator> MergedIterator;
typedef boost::iterator_range<MergedIterator> IteratorRange;
return IteratorRange(
MergeIterator( c1.begin(), c1.end(), c2.begin(), c2.end() ),
MergeIterator( c2.end(), c1.end(), c2.begin(), c2.end() ) );
}
// Now use a bit of magic to define merged_iterator<...>
// And you'll be able to write
BOOST_FOREACH( std::pair<int, int> i, concat_containers( map1, map2 ) )
{
// Do whatever you want here
}
#3
In addition to 1800's solution, which I would recommend, there's also various hacky solutions:
除了1800的解决方案,我建议,还有各种hacky解决方案:
for (int stage = 0; stage < 2; stage++) {
BOOST_FOREACH(int i, stage == 0 ? map1 : map2) {
...
}
}
typedef std::map<int, int> intmap;
std::vector<intmap *> v;
v.push_back(&map1);
v.push_back(&map2);
BOOST_FOREACH(intmap *m, v) {
BOOST_FOREACH(int i, *m) {
...
}
}
Note: when I see colleagues write code like this, sometimes I am overcome by an irresistible urge to go strangle them. Use at your own risk.
注意:当我看到同事写下这样的代码时,有时候我会被一种不可抗拒的冲动所克服。使用风险由您自己承担。
#4
The easiest way is like this:
最简单的方法是这样的:
std::map<int, int> map1, map2;
int key, value;
BOOST_FOREACH(boost::tie(key, value), boost::join(map1, map2))
{
// do steps 1-5 here...
}
And don't worry those commas won't confuse the preprocessor because of the parenthesis.
不要担心,由于括号,这些逗号不会混淆预处理器。
#5
Of the top of my head, I'd try
在我的头脑中,我会尝试
std::map<int, int> map1, map2;
std::map<int, int>& maps = { map1, map2 }
BOOST_FOREACH(std::map<int, int> map, maps)
BOOST_FOREACH(int i, map)
{
// do steps 1-5 here...
}
#6
It's explained here.
它在这里解释。
You can do this:
你可以这样做:
std::map<int,int> m;
typedef std::pair<int,int> pair_t;
BOOST_FOREACH(pair_t p, m)
#1
You could define a function:
你可以定义一个函数:
typedef std::map<int, int> IntMap;
void doStuffWithInt(IntMap::value_type &i)
{
// steps 1 to 5
}
BOOST_FOREACH(IntMap::value_type &i, map1)
doStuffWithInt(i);
BOOST_FOREACH(IntMap::value_type &i, map2)
doStuffWithInt(i);
Although in that case it might be even simpler to use std::for_each
:
虽然在这种情况下使用std :: for_each可能更简单:
for_each(map1.begin(), map1.end(), doStuffWithInt);
for_each(map2.begin(), map2.end(), doStuffWithInt);
#2
The idea here is to write a special type of iterators to virtually merge two containers, as far as BOOST_FOREACH is concerned. Note that i am not creating a new container out of the two existing ones. I am simply jumping from the first container's end() to the second container's begin() iterator. I did not try and write the actual merged_iterator class, but although it might a bit long to write, it's not technically difficult. I am actually surprised not to have found something like that using google. I did not look for long, though !
这里的想法是编写一种特殊类型的迭代器来虚拟地合并两个容器,就BOOST_FOREACH而言。请注意,我不是从现有的两个容器中创建一个新容器。我只是从第一个容器的end()跳转到第二个容器的begin()迭代器。我没有尝试编写实际的merged_iterator类,但是虽然编写起来可能有点长,但这在技术上并不困难。我真的很惊讶没有使用谷歌找到类似的东西。不过我看起来并不长久!
template<typename Container>
boost::iterator_range<
merged_iterator<Container::iterator>
>
concat_containers( Container& c1, Container& c2 )
{
typedef merged_iterator<typename Container::iterator> MergedIterator;
typedef boost::iterator_range<MergedIterator> IteratorRange;
return IteratorRange(
MergeIterator( c1.begin(), c1.end(), c2.begin(), c2.end() ),
MergeIterator( c2.end(), c1.end(), c2.begin(), c2.end() ) );
}
// Now use a bit of magic to define merged_iterator<...>
// And you'll be able to write
BOOST_FOREACH( std::pair<int, int> i, concat_containers( map1, map2 ) )
{
// Do whatever you want here
}
#3
In addition to 1800's solution, which I would recommend, there's also various hacky solutions:
除了1800的解决方案,我建议,还有各种hacky解决方案:
for (int stage = 0; stage < 2; stage++) {
BOOST_FOREACH(int i, stage == 0 ? map1 : map2) {
...
}
}
typedef std::map<int, int> intmap;
std::vector<intmap *> v;
v.push_back(&map1);
v.push_back(&map2);
BOOST_FOREACH(intmap *m, v) {
BOOST_FOREACH(int i, *m) {
...
}
}
Note: when I see colleagues write code like this, sometimes I am overcome by an irresistible urge to go strangle them. Use at your own risk.
注意:当我看到同事写下这样的代码时,有时候我会被一种不可抗拒的冲动所克服。使用风险由您自己承担。
#4
The easiest way is like this:
最简单的方法是这样的:
std::map<int, int> map1, map2;
int key, value;
BOOST_FOREACH(boost::tie(key, value), boost::join(map1, map2))
{
// do steps 1-5 here...
}
And don't worry those commas won't confuse the preprocessor because of the parenthesis.
不要担心,由于括号,这些逗号不会混淆预处理器。
#5
Of the top of my head, I'd try
在我的头脑中,我会尝试
std::map<int, int> map1, map2;
std::map<int, int>& maps = { map1, map2 }
BOOST_FOREACH(std::map<int, int> map, maps)
BOOST_FOREACH(int i, map)
{
// do steps 1-5 here...
}
#6
It's explained here.
它在这里解释。
You can do this:
你可以这样做:
std::map<int,int> m;
typedef std::pair<int,int> pair_t;
BOOST_FOREACH(pair_t p, m)