Resorting a map (copying a map to another with different Compare)

N

nw

Hi,

I'd like to be able to re-sort a map (a curious aspiration perhaps). I
think basically what I'd like to do is copy one map into another that
uses a different Compare function. I was wondering if there was an
easy way of doing this in general. Or what strategy I could use to do
it?

I've tried something like this:

template<class map1_type,class map2_type>
void copy_map(map1_type &m1,map2_type &m2,int depth) {

if(depth > 0) {
map1_type::const_iterator i = m1.begin();
for(;i != m1.end();++i) {
copy_map(i,m2[i->first],depth-1);
}
} else {
map1_type::const_iterator i = m1.begin();
for(;i != m1.end();++i) {
m2[i->first] = m1[i->first];
}
}
}

But this fails to even compile. Does anyone have any ideas here?
 
M

Michael Oswald

Am 11.03.2010 15:12, schrieb nw:
Hi,

I'd like to be able to re-sort a map (a curious aspiration perhaps). I
think basically what I'd like to do is copy one map into another that
uses a different Compare function. I was wondering if there was an
easy way of doing this in general. Or what strategy I could use to do
it?

Maybe boost::multi_index? At least you could avoid the copying.

lg,
Michael
 
N

nw

nw said:
I'd like to be able to re-sort a map (a curious aspiration perhaps). I
think basically what I'd like to do is copy one map into another that
uses a different Compare function. I was wondering if there was an
easy way of doing this in general. Or what strategy I could use to do
it?
I've tried something like this:
template<class map1_type,class map2_type>
void copy_map(map1_type &m1,map2_type &m2,int depth) {
  if(depth > 0) {
    map1_type::const_iterator i = m1.begin();
    for(;i != m1.end();++i) {
      copy_map(i,m2[i->first],depth-1);
    }
  } else {
    map1_type::const_iterator i = m1.begin();
    for(;i != m1.end();++i) {
      m2[i->first] = m1[i->first];
    }
  }
}
But this fails to even compile. Does anyone have any ideas here?

In general, you can copy one map into another like this:

        map2_type m2(m1.begin(), m1.end());

--
   Pete
Roundhouse Consulting, Ltd. (www.versatilecoding.com) Author of
"The Standard C++ Library Extensions: a Tutorial and Reference"
(www.petebecker.com/tr1book)

So I think the problem is that in general I'm trying to do this with
maps containing maps e.g.:

#include <map>
#include <iostream>

using namespace std;

class numstr_compare {

public:
inline bool operator()(const string &k1,const string &k2) const {
std::cout << "numstr compare" << std::endl;

for(size_t n=0;n<k1.size();n++) { if(!(((k1[n] >= '0') && (k1[n]
<= '9')) || k1[n] == '.')) {return k1 < k2; std::cout << "strcomp1" <<
std::endl;} }
std::cout << "str: " << k1 << std::endl;

for(size_t n=0;n<k2.size();n++) { if(!(((k2[n] >= '0') && (k2[n]
<= '9')) || k2[n] == '.')) {return k1 < k2; std::cout << "strcomp2" <<
std::endl;} }
std::cout <<" str: " << k2 << std::endl;

if(k1.size() == 0) {return k1 < k2;}
if(k2.size() == 0) {return k1 < k2;}

float k1_double = atof(k1.c_str());
float k2_double = atof(k2.c_str());
return k1_double < k2_double;

}
};


int main() {

map<string,map<string,string> > m1;

m1["stuff"] = map<string,string>();
m1["astuff"] = map<string,string>();
m1["321"] = map<string,string>();
m1["432"] = map<string,string>();
m1["12323"] = map<string,string>();
m1["123"] = map<string,string>();
m1["1"] = map<string,string>();

map<string,map<string,numstr_compare>,numstr_compare>
m2(m1.begin(),m1.end());
}

Is there any neat solution here?
 
N

nw

So to clarify what I'm after is something that does this, but is
generic to different depths and map types:

#include <map>
#include <iostream>

using namespace std;

class more {

public:
inline bool operator()(const string &k1,const string &k2) const {
return k1 > k2;
}
};


void copy_map(map<string,map<string,string> > &m1,
map<string,map<string,string,more>,more> &m2) {

map<string,map<string,string> >::iterator i = m1.begin();

for(;i != m1.end();++i) {
map<string,string>::iterator i2 = (*i).second.begin();
for(;i2 != (*i).second.end();++i2) {
m2[(*i).first][(*i2).first] = (*i2).second;
}
}
}

int main() {

map<string,map<string,string> > m1;
map<string,map<string,string,more>,more> m2;

map<string,string> m3 = map<string,string>();
m3["1thing"] = "3343";
m3["2thing"] = "943";
m3["3thing"] = "23343";


m1["stuff"] = m3;
m1["astuff"] = m3;
m1["321"] = m3;
m1["432"] = m3;
m1["12323"] = m3;
m1["123"] = m3;
m1["1"] = m3;

copy_map(m1,m2);

map<string,map<string,string,more>,more>::iterator i = m2.begin();
for(;i != m2.end();++i) {
map<string,string,more>::iterator i2 = (*i).second.begin();
for(;i2 != (*i).second.end();++i2) {
std::cout said:
first][i2->first] << std::endl;
}
}
}
 
P

Pavel

nw said:
Hi,

I'd like to be able to re-sort a map (a curious aspiration perhaps). I
think basically what I'd like to do is copy one map into another that
uses a different Compare function. I was wondering if there was an
easy way of doing this in general. Or what strategy I could use to do
it?

I've tried something like this:

template<class map1_type,class map2_type>
void copy_map(map1_type&m1,map2_type&m2,int depth) {

if(depth> 0) {
map1_type::const_iterator i = m1.begin();
for(;i != m1.end();++i) {
copy_map(i,m2[i->first],depth-1);
}
} else {
map1_type::const_iterator i = m1.begin();
for(;i != m1.end();++i) {
m2[i->first] = m1[i->first];
}
}
}

But this fails to even compile. Does anyone have any ideas here?
The issue is that you "depth" is not a template (compile-time) but a
function (run-time) parameter. Thus, the recursive instantiation of a
template function does not have a stop condition.. The below seems to
work (hopefully this is what you meant to do):

-----------cut here---------
#include <functional>
#include <iostream>
#include <map>
using namespace std;

template <class M1, class M2, unsigned depth>
struct MapCopier {
static M2 Copy(const M1 &src) {
M2 dst;
for (typename M1::const_iterator i1 = src.begin(); i1 != src.end();
++i1) {
typedef typename M1::mapped_type M1Next;
typedef typename M2::mapped_type M2Next;
dst[i1->first] = MapCopier<M1Next, M2Next, depth - 1>
::Copy(i1->second);
}
return dst;
}
};

template <class M1, class M2>
struct MapCopier<M1, M2, 1> {
static M2 Copy(const M1 &src) {
M2 dst(src.begin(), src.end());
return dst;
}
};

struct RevComp : public binary_function<int, int, bool>
{ bool operator()(int x, int y) const { return x > y; } };

typedef map<int, map<int, int> > IM1;
typedef map<int, map<int, int, RevComp>, RevComp> IM2;


int main() {
IM1 m1;
m1[0][0] = 7;
m1[0][1] = 8;
m1[1][0] = 9;
m1[1][1] = 10;
IM2 m2 = MapCopier<IM1, IM2, 2>::Copy(m1);
for (IM2::iterator i = m2.begin(); i != m2.end(); ++i)
for (IM2::value_type::second_type::iterator j = i->second.begin();
j != i->second.end(); ++j)
cout << "m2[" << i->first << "][" << j->first << "]=" << j->second
<< '\n';
return 0;
}
-----------cut here---------

Hope this helps,
Pavel
 
P

Permostat

Hi,

I'd like to be able to re-sort a map (a curious aspiration perhaps). I
think basically what I'd like to do is copy one map into another that
uses a different Compare function. I was wondering if there was an
easy way of doing this in general. Or what strategy I could use to do
it?

I've tried something like this:

template<class map1_type,class map2_type>
void copy_map(map1_type &m1,map2_type &m2,int depth) {

  if(depth > 0) {
    map1_type::const_iterator i = m1.begin();
    for(;i != m1.end();++i) {
      copy_map(i,m2[i->first],depth-1);
    }
  } else {
    map1_type::const_iterator i = m1.begin();
    for(;i != m1.end();++i) {
      m2[i->first] = m1[i->first];
    }
  }

}

But this fails to even compile. Does anyone have any ideas here?

Blast it with piss.

sperm-
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,755
Messages
2,569,536
Members
45,007
Latest member
obedient dusk

Latest Threads

Top