Map inside a map sorting

Hi all, I'm relatively new to programming in C++ and I need some help. I have a map which contains a multiset and another map

std::map<std::multiset<int>, std::map<int, int> >

And I need to sort the whole map according to the mapped value of the inside map, then output the data from the keys i.e. from the multiset and the first value of the inside map.
I have tried to create a vector of pairs

std::vector<pair<std::map<:std::multiset<int>, std::map<int, int> >, int> >

and populate the first element with the map and where the second integer of the pair will be the mapped value to sort. I have tried iterating over the map to populate the vector but I'm not sure how to do so. Could someone help please, an example would be much appreciated.
Last edited on
Wow.

Perhaps if you explained how you ended up with that mess and where you're going with it, we be able to provide a more sane implementation.
I know, it's getting me frustrated haha.

Well, it's for my physics project. Long story short, I'm running a monte carlo particle accelerator simulation over a certain amount of events. In the multiset I'm storing the daughter decay PDGID codes, in the map, the key value is one of the particles, and the mapped value is how many times this event takes place.

What I'm trying to do is arrange all of the information in descending order according to the mapped value.

Then with everything ordered, iterate through the multiset display each ID then through the map to get the keyed value. Does this make sense?
Simple, brute force:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
#include <iostream>
#include <vector>
#include <map>
#include <set>
#include <tuple>
#include <algorithm>

int main()
{
    const std::map< std::multiset<int>, std::map<int, int> > map =
    {
        { { 0, 1       },    { {0,18}, {1,13}, {5,14}, {6,12} } },
        { { 0, 1, 2    },    { {0,14}, {1,17}, {2,14}         }  },
        { { 1, 2       },    { {3,11}, {5,19}, {6,17}, {7,18} } },
        { { 1, 2, 3, 4 },    { {0,17}, {1,11}, {2,10},        } },
        { { 2, 3       },    { {7,16}, {8,13}, {9,13}         } }
    };

    using tuple_type = std::tuple< int /* value(map) */, int /* key(map) */, std::multiset<int> > ;
    std::vector< tuple_type > vec ;

    for( const auto& v : map )
    {
        for( const auto& pair : v.second )
             vec.push_back( std::make_tuple( pair.second, pair.first, v.first ) ) ;
    }

    std::sort( vec.begin(), vec.end() ) ;

    for( const auto& tup : vec )
    {
        std::cout << "map: { value " <<  std::get<0>(tup) << " key " << std::get<1>(tup) << " } " << "  multiset { " ;
        for( int v : std::get<2>(tup) ) std::cout << v << ' ' ;
        std::cout << " }\n" ;
    }
}

http://coliru.stacked-crooked.com/a/780b5f4be2a208e3


If the number of multisets and/or their size is large, we wouldn't want to copy them on a massive scale:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
#include <iostream>
#include <vector>
#include <map>
#include <set>
#include <functional>
#include <tuple>
#include <algorithm>

int main()
{
    const std::map< std::multiset<int>, std::map<int, int> > map =
    {
        { { 0, 1       },    { {0,18}, {1,13}, {5,14}, {6,12} } },
        { { 0, 1, 2    },    { {0,14}, {1,17}, {2,14}        }  },
        { { 1, 2       },    { {3,11}, {5,19}, {6,17}, {7,18} } },
        { { 1, 2, 3, 4 },    { {0,17}, {1,11}, {2,10},       } },
        { { 2, 3       },    { {7,16}, {8,13}, {9,13}        } }
    };

    // we don't want large numbers of copies of multisets
    using wrapped_multiset_type = std::reference_wrapper< const std::multiset<int> > ;

    using tuple_type = std::tuple< int /* value(map) */, int /* key(map) */, wrapped_multiset_type > ;
    std::vector< tuple_type > vec ;

    for( const auto& v : map )
    {
        for( const auto& pair : v.second )
             vec.push_back( std::make_tuple( pair.second, pair.first, std::cref(v.first) ) ) ;
    }

    const auto cmp = []( const tuple_type& a, const tuple_type& b ){ return std::get<0>(a) < std::get<0>(b) ; } ;
    std::sort( vec.begin(), vec.end(), cmp ) ;

    for( const auto& tup : vec )
    {
        std::cout << "map: { value " <<  std::get<0>(tup) << " key " << std::get<1>(tup) << " } " << "  multiset { " ;
        for( int v : std::get<2>(tup).get() ) std::cout << v << ' ' ;
        std::cout << " }\n" ;
    }
}

http://coliru.stacked-crooked.com/a/af9b605b8cd2e588
Thank you very much for your help! I will give this a run
I'm getting this error code
#error This file requires compiler and library support for the ISO C++ 2011 standard. 
This support is currently experimental, and must be enabled with the -std=c++11 or -std=gnu++11 compiler options.

And I get quite a lot of errors for the tuples and expected ; in front of =. Could you give me some more help. Or is there a way to enable C++11. I compile my code using
rivet-buildplugin RivetAnalysis.so fun.cc MyAnalysis_new8.cc -I/home/adam/Sherpa/Rivet-2.2.0/include
Last edited on
I don't know what rivet-buildplugin does; if it forwards compiler options, then adding -std=c++11 should suffice.

rivet-buildplugin -std=c++11 RivetAnalysis.so fun.cc MyAnalysis_new8.cc -I/home/adam/Sherpa/Rivet-2.2.0/include

Try that; if it does not solve the problem, post the error diagnostic.
When addidng -std=c++11 to the compiling I get this error.
adam@adam-XPS-L501X:~/dimuon_asymmetry$ rivet-buildplugin -std=c++11 RivetAnalysis.so fun.cc MyAnalysis_new8.cc -I/home/adam/Sherpa/Rivet-2.2.0/include
/home/adam/Sherpa/install/bin/rivet-buildplugin: line 106: set: -s: invalid option
set: usage: set [-abefhkmnptuvxBCHP] [-o option-name] [--] [arg ...]
basename: missing operand
Try 'basename --help' for more information.
basename: missing operand
Try 'basename --help' for more information.
Using default library name 'RivetAnalysis.so'
/usr/bin/g++ -o "RivetAnalysis.so" -shared -fPIC -I/home/adam/Sherpa/install/include -I/home
/adam/Sherpa/install/include -I/home/adam/Sherpa/install/include -I/home/adam/Sherpa/install/include 
-I/usr/include -pedantic -ansi -Wall -Wno-long-long -Wno-format -Werror=uninitialized -Werror=delete-
non-virtual-dtor -O2 -Wl,--no-as-needed -L/home/adam/Sherpa/install/lib -L/home/adam/Sherpa
/install/lib -L/home/adam/Sherpa/install/lib -Wl,-rpath,/home/adam/Sherpa/install/lib -lm -L/home
/adam/Sherpa/install/lib -lfastjettools -lfastjet -lfastjetplugins -lsiscone_spherical -lsiscone -std=c++11 
RivetAnalysis.so fun.cc MyAnalysis_new8.cc -I/home/adam/Sherpa/Rivet-2.2.0/include -lRivet
g++: error: RivetAnalysis.so: No such file or directory
Last edited on
Surprisingly I changed the code to
rivet-buildplugin RivetAnalysis.so fun.cc MyAnalysis_new8.cc -std=c++11 -I/home/adam/Sherpa/Rivet-2.2.0/include
And it has compiled
Thank you very much, it works perfectly!!
Topic archived. No new replies allowed.