用于迭代多重映射的某些元素的设计运算符++
Design operator++ for iterating over certain elements of a multimap
我有以下 class 声明:
class Dictionnary{
private:
map< int,list<string> > data;
public:
bool isPrime();
class prime_iterator{
private:
map< int,list<string> >::iterator it;
public:
iterator(){}
prime_iterator & operator++(){
++it;
while(it != data.end() && !isPrime(it->first)){
++it;
}
return it;
}
...
};
旨在提供对 map<int,list<string>>
的主键的迭代器。我不确定 operator++ 是否得到很好的实施。
首先,it != data.end()
访问外部class是否是一个好的设计?其次,operator++ return 是正确的还是应该 return 仅 prime_iterator?另外,你能想出更好的办法吗?
我的建议是始终尝试在别处寻找解决方案 - 如果找不到 - 那么只能自己创建:
对于你的情况,它看起来是这样的:
#include <boost/iterator/filter_iterator.hpp>
using DataMap = std::map<int, std::list<std::string>>;
struct is_prime_number {
bool operator()(const DataMap::value_type& x) { return x.first % 2 == 0; }
}; // I know this is just is_even - not is_prime :D
using DataMapPrimeIter = boost::filter_iterator<is_prime_number, DataMap::iterator>;
inline DataMapPrimeIter only_prime_begin(DataMap& dataMap)
{
return boost::make_filter_iterator<is_prime_number>(dataMap.begin(), dataMap.end());
}
inline DataMapPrimeIter only_prime_end(DataMap& dataMap)
{
return boost::make_filter_iterator<is_prime_number>(dataMap.end(), dataMap.end());
}
和用法:
int main()
{
DataMap dataMap{{1,{"A","B"}}, {2,{"C", "D", "E"}}};
for (auto i = only_prime_begin(dataMap), end = only_prime_end(dataMap); i != end; ++i)
{
std::cout << i->first << i->second.front() << std::endl;
}
}
如果你想有自己的实现,或者你不能在你的项目中使用 boost - 然后查看 boost 实现 - 它是免费的...
我的拙劣解决方案。 typedef
只是为了方便。
#include <iterator>
#include <iostream>
#include <map>
#include <string>
#include <vector>
#include <algorithm>
typedef std::map<int, std::string> map_t;
class Dictionary {
private:
map_t& m_map;
public:
class prime_iterator {
public:
prime_iterator( map_t::iterator begin, map_t::iterator end )
: m_current(begin), m_end(end) {
runUntilPrime();
}
prime_iterator& operator++() {
m_current++;
runUntilPrime();
return *this;
}
bool operator != (prime_iterator other) {
return other.m_current != m_current;
}
map_t::value_type& operator* () {
return *m_current;
}
private:
map_t::iterator m_current;
map_t::iterator m_end;
bool isPrime(int x) {
std::vector<int> primes = { 1, 2, 3, 5, 7, 11, 13, 17 };
return std::find( primes.begin(), primes.end(), x ) != primes.end();
}
void runUntilPrime() {
while( m_current != m_end && !isPrime(m_current->first) ) {
m_current++;
}
}
};
Dictionary( map_t& tmap )
: m_map(tmap) {}
prime_iterator begin() {
return prime_iterator( m_map.begin(), m_map.end() );
}
prime_iterator end () {
return prime_iterator(m_map.end(), m_map.end());
}
};
int main( int argc, char** argv ) {
map_t map;
map.emplace(0, "zero");
map.emplace(1, "one");
map.emplace(2, "two");
map.emplace(3, "three");
map.emplace(4, "four");
map.emplace(5, "five");
map.emplace(6, "six");
map.emplace(7, "seven");
map.emplace(8, "eight");
map.emplace(9, "nine");
map.emplace(10, "ten");
map.emplace(13, "thirteen");
Dictionary dict( map );
for( auto p : dict ) {
std::cout << p.first << "\t" << p.second << std::endl;
}
return 0;
}
我有以下 class 声明:
class Dictionnary{
private:
map< int,list<string> > data;
public:
bool isPrime();
class prime_iterator{
private:
map< int,list<string> >::iterator it;
public:
iterator(){}
prime_iterator & operator++(){
++it;
while(it != data.end() && !isPrime(it->first)){
++it;
}
return it;
}
...
};
旨在提供对 map<int,list<string>>
的主键的迭代器。我不确定 operator++ 是否得到很好的实施。
首先,it != data.end()
访问外部class是否是一个好的设计?其次,operator++ return 是正确的还是应该 return 仅 prime_iterator?另外,你能想出更好的办法吗?
我的建议是始终尝试在别处寻找解决方案 - 如果找不到 - 那么只能自己创建:
对于你的情况,它看起来是这样的:
#include <boost/iterator/filter_iterator.hpp>
using DataMap = std::map<int, std::list<std::string>>;
struct is_prime_number {
bool operator()(const DataMap::value_type& x) { return x.first % 2 == 0; }
}; // I know this is just is_even - not is_prime :D
using DataMapPrimeIter = boost::filter_iterator<is_prime_number, DataMap::iterator>;
inline DataMapPrimeIter only_prime_begin(DataMap& dataMap)
{
return boost::make_filter_iterator<is_prime_number>(dataMap.begin(), dataMap.end());
}
inline DataMapPrimeIter only_prime_end(DataMap& dataMap)
{
return boost::make_filter_iterator<is_prime_number>(dataMap.end(), dataMap.end());
}
和用法:
int main()
{
DataMap dataMap{{1,{"A","B"}}, {2,{"C", "D", "E"}}};
for (auto i = only_prime_begin(dataMap), end = only_prime_end(dataMap); i != end; ++i)
{
std::cout << i->first << i->second.front() << std::endl;
}
}
如果你想有自己的实现,或者你不能在你的项目中使用 boost - 然后查看 boost 实现 - 它是免费的...
我的拙劣解决方案。 typedef
只是为了方便。
#include <iterator>
#include <iostream>
#include <map>
#include <string>
#include <vector>
#include <algorithm>
typedef std::map<int, std::string> map_t;
class Dictionary {
private:
map_t& m_map;
public:
class prime_iterator {
public:
prime_iterator( map_t::iterator begin, map_t::iterator end )
: m_current(begin), m_end(end) {
runUntilPrime();
}
prime_iterator& operator++() {
m_current++;
runUntilPrime();
return *this;
}
bool operator != (prime_iterator other) {
return other.m_current != m_current;
}
map_t::value_type& operator* () {
return *m_current;
}
private:
map_t::iterator m_current;
map_t::iterator m_end;
bool isPrime(int x) {
std::vector<int> primes = { 1, 2, 3, 5, 7, 11, 13, 17 };
return std::find( primes.begin(), primes.end(), x ) != primes.end();
}
void runUntilPrime() {
while( m_current != m_end && !isPrime(m_current->first) ) {
m_current++;
}
}
};
Dictionary( map_t& tmap )
: m_map(tmap) {}
prime_iterator begin() {
return prime_iterator( m_map.begin(), m_map.end() );
}
prime_iterator end () {
return prime_iterator(m_map.end(), m_map.end());
}
};
int main( int argc, char** argv ) {
map_t map;
map.emplace(0, "zero");
map.emplace(1, "one");
map.emplace(2, "two");
map.emplace(3, "three");
map.emplace(4, "four");
map.emplace(5, "five");
map.emplace(6, "six");
map.emplace(7, "seven");
map.emplace(8, "eight");
map.emplace(9, "nine");
map.emplace(10, "ten");
map.emplace(13, "thirteen");
Dictionary dict( map );
for( auto p : dict ) {
std::cout << p.first << "\t" << p.second << std::endl;
}
return 0;
}