1

I need to flip a map (key => value in value => key). However, I want the option to sort in asc/desc order.

I think in using greater or less!

E.g.: map<int, int, greater<int> > map

Based on posting Sorting std::map using value, I have the partial solution ...

template<typename A, typename B>
pair<B, A> flipPair(const pair<A, B> &p) {
    return pair<B,A>(p.second, p.first);
}

template<typename A, typename B>
map<B, A> flipMap(const map<A, B> &src) {
    map<B, A> dst;
    transform(src.begin(), src.end(), inserter(dst, dst.begin()), flipPair<A, B>);
    return dst;
}

How to add arguments to select greater or less?

I tried this but does not work!!

template<typename A, typename B, typename Comp = less<A> >
map<B, A, Comp> flipMap(const map<A, B> &src) {
    map<B, A, Comp> dst;
    transform(src.begin(), src.end(), inserter(dst, dst.begin()), flipPair<A, B>);
    return dst;
}

Erro: error: default template arguments may not be used in function templates without -std=c++11 or -std=gnu++11

Community
  • 1
  • 1
Alan Valejo
  • 1,305
  • 3
  • 24
  • 44
  • You could always try [Boost Bimap](http://www.boost.org/doc/libs/1_42_0/libs/bimap/doc/html/index.html#bimap.preface). – jrok Sep 11 '13 at 14:33

2 Answers2

2

You almost have it with your last code snippet, you just forgot to use the Compare template type you allow.

template<typename A, typename B, typename Compare = less<A> >
map<B, A, Compare> flipMap(const map<A, B> &src)
{
    map<B, A, Compare> dst;
    transform(src.begin(), src.end(), inserter(dst, dst.begin()), flipPair<A, B>);

    return dst;
}
Mark B
  • 95,107
  • 10
  • 109
  • 188
1

You need to allow using custom comparator. std::map orders keys based on the comparator it is told to use. By default, it is std::less, which in turn uses operator < for the key type. In order to use other comparator, you can add it to the function's parameter list and specify it in the new map's constructor:

template<typename A, typename B, typename Comp = std::less<B> >
map<B, A, Comp> flipMap(const map<A, B> &src, const Comp& comp = Comp()) {
    map<B, A> dst(comp);
    transform(src.begin(), src.end(), inserter(dst, dst.begin()), flipPair<A, B>);
    return dst;
}

This way gives sensible default behaviour, and allows arbitrary customization via the comparator, if necessary. To obtain reverse order, use std::greater as a comparator:

std::map<B, A> flippedDesc = flipMap(original, std::greater<B>());

Note: The above code is C++11 because of default function template argument. You can still use it with C++03 as long as the = std::less<B> is removed, and specify function object/comparator type explicitly each time.

Marcin Łoś
  • 3,226
  • 1
  • 19
  • 21