Sorting a multimap in alphabetical order

Nov 20, 2014 at 7:27pm
closed account (EwCjE3v7)
How can I sort a multimap in alphabetical order? I would think it would go something like below but that gives me a segmentation fault.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
bool alpha_order(const string ls, const string rs)
{
	return ls < rs;
}

int main()
{	
	multimap<string, string, decltype(alpha_order)*> authors = {{"Charlie Wilson", "Gone Far"},
								{"James Wilson", "The Water"},
								{"Charlie Wilson", "Clocks Gone"}};
	
	

	return 0;
}
Last edited on Nov 20, 2014 at 7:28pm
Nov 20, 2014 at 9:03pm
Just use the default for the comparison function. (The default uses the < operator.)

1
2
3
4
5
6
7
int main()
{	
    std::multimap< std::string, std::string > authors = { { "Charlie Wilson", "Gone Far" },
                                                          { "James Wilson", "The Water" },
                                                          { "Charlie Wilson", "Clocks Gone" } };
    // ...
}
Nov 21, 2014 at 4:44pm
closed account (EwCjE3v7)
Oh that was a little stupid of me. Keys are sorted alphabetically, how may I sort the values alphabetically if the authors name was the same.

1
2
3
4
5
6
7
8
9
10
11
12
13
int main()
{	
	multimap<string, string> authors = {{"Charlie Wilson", "Gone Far"},
										{"James Wilson", "The Water"},
										{"Charlie Wilson", "Clocks Gone"}};
	
	for (const auto &w : authors) {
		cout << w.first << " : " << w.second << endl;
	}
	

	return 0;
}


output:


Charlie Wilson : Gone Far
Charlie Wilson : Clocks Gone
James Wilson : The Water



I would like it to be like this;


Charlie Wilson : Clocks Gone
Charlie Wilson : Gone Far
James Wilson : The Water

Nov 21, 2014 at 5:07pm
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
#include <iostream>
#include <set>
#include <map>
#include <utility>

int main()
{
    std::multimap< std::string, std::string > authors =
    {
        { "Charlie Wilson", "Gone Far" },
        { "James Wilson", "The Water" },
        { "Charlie Wilson", "Clocks Gone" },
        { "James Wilson", "Zebra" },
        { "James Wilson", "Aardvark" },
        { "Charlie Wilson", "Fargone Clocks" }
    };

    std::set< std::pair< std::string, std::string > > books( authors.begin(), authors.end() ) ;
    for( const auto& pair : books )
        std::cout << "author: '" << pair.first << "' book: '" << pair.second << "'\n" ;
}

http://coliru.stacked-crooked.com/a/bf659cd8db10c984
Nov 21, 2014 at 5:12pm
I believe that multimap has no guarantee on the order of the values that share a common key. So you will have to sort them yourself, or you could use a map<string, set<string> > instead. This would map an author to a set of titles. The titles would also be sorted alphabetically.
Nov 21, 2014 at 6:13pm
closed account (EwCjE3v7)
@JLBorges Thank you :)

@dhayden That would not work because the books would not be corresponding to the right authors.
Nov 21, 2014 at 6:31pm
That would not work because the books would not be corresponding to the right authors.


Read dhayden post more carefully.

He suggested using
map<string>, set<string> >

The authors entries would be unique because it is a map, not a multimap.
Each author then has it's own set<> of titles which would be in alphabetical order.

When you go to add an author and title, you would have to search to see if the author exists, if so, then you would add just the title to the set<> for that author. If the author does not exist, you would add the author to the map and the title to that author's set.


Nov 21, 2014 at 6:35pm
It would work. Though it would change the structure of your program (and maintaining that structure throughout the program may be somewhat wasteful, unless most authors had several books against their name).

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
#include <iostream>
#include <set>
#include <map>
#include <utility>

int main()
{
    std::map< std::string, std::set<std::string> > authors =
    {
        { "Charlie Wilson", { "Gone Far", "Clocks Gone", "Fargone Clocks" } },
        { "James Wilson", { "The Water", "Zebra", "Aardvark" } }
    };

    authors[ "Charlie Wilson" ].insert( "Clocks Gone Far" ) ;
    authors[ "Borges" ].insert( "The Garden of Forking Paths" ) ;

    for( const auto& pair : authors )
    {
        std::cout << "\nauthor: '" << pair.first << "'\n" ;
        for( const auto& str : pair.second ) std::cout << "\tbook: '" << str << "'\n" ;
    }
}

http://coliru.stacked-crooked.com/a/9b3e9a2825c96415
Last edited on Nov 21, 2014 at 6:46pm
Topic archived. No new replies allowed.