1 /* Boost.MultiIndex example of use of hashed indices.
2 *
3 * Copyright 2003-2008 Joaquin M Lopez Munoz.
4 * Distributed under the Boost Software License, Version 1.0.
5 * (See accompanying file LICENSE_1_0.txt or copy at
6 * http://www.boost.org/LICENSE_1_0.txt)
7 *
8 * See http://www.boost.org/libs/multi_index for library home page.
9 */
10
11 #if !defined(NDEBUG)
12 #define BOOST_MULTI_INDEX_ENABLE_INVARIANT_CHECKING
13 #define BOOST_MULTI_INDEX_ENABLE_SAFE_MODE
14 #endif
15
16 #include <boost/multi_index_container.hpp>
17 #include <boost/multi_index/hashed_index.hpp>
18 #include <boost/multi_index/member.hpp>
19 #include <boost/multi_index/ordered_index.hpp>
20 #include <boost/tokenizer.hpp>
21 #include <iomanip>
22 #include <iostream>
23 #include <string>
24
25 using boost::multi_index_container;
26 using namespace boost::multi_index;
27
28 /* word_counter keeps the ocurrences of words inserted. A hashed
29 * index allows for fast checking of preexisting entries.
30 */
31
32 struct word_counter_entry
33 {
34 std::string word;
35 unsigned int occurrences;
36
word_counter_entryword_counter_entry37 word_counter_entry(std::string word_):word(word_),occurrences(0){}
38 };
39
40 /* see Compiler specifics: Use of member_offset for info on
41 * BOOST_MULTI_INDEX_MEMBER
42 */
43
44 typedef multi_index_container<
45 word_counter_entry,
46 indexed_by<
47 ordered_non_unique<
48 BOOST_MULTI_INDEX_MEMBER(word_counter_entry,unsigned int,occurrences),
49 std::greater<unsigned int> /* sorted beginning with most frequent */
50 >,
51 hashed_unique<
52 BOOST_MULTI_INDEX_MEMBER(word_counter_entry,std::string,word)
53 >
54 >
55 > word_counter;
56
57 /* utilities */
58
59 template<typename T>
60 struct increment
61 {
operator ()increment62 void operator()(T& x)const{++x;}
63 };
64
65 typedef boost::tokenizer<boost::char_separator<char> > text_tokenizer;
66
main()67 int main()
68 {
69 /* boostinspect:noascii */
70
71 std::string text=
72 "En un lugar de la Mancha, de cuyo nombre no quiero acordarme, no ha "
73 "mucho tiempo que viv�a un hidalgo de los de lanza en astillero, adarga "
74 "antigua, roc�n flaco y galgo corredor. Una olla de algo m�s vaca que "
75 "carnero, salpic�n las m�s noches, duelos y quebrantos los s�bados, "
76 "lantejas los viernes, alg�n palomino de a�adidura los domingos, "
77 "consum�an las tres partes de su hacienda. El resto della conclu�an sayo "
78 "de velarte, calzas de velludo para las fiestas, con sus pantuflos de lo "
79 "mesmo, y los d�as de entresemana se honraba con su vellor� de lo m�s "
80 "fino. Ten�a en su casa una ama que pasaba de los cuarenta, y una "
81 "sobrina que no llegaba a los veinte, y un mozo de campo y plaza, que "
82 "as� ensillaba el roc�n como tomaba la podadera. Frisaba la edad de "
83 "nuestro hidalgo con los cincuenta a�os; era de complexi�n recia, seco "
84 "de carnes, enjuto de rostro, gran madrugador y amigo de la caza. "
85 "Quieren decir que ten�a el sobrenombre de Quijada, o Quesada, que en "
86 "esto hay alguna diferencia en los autores que deste caso escriben; "
87 "aunque, por conjeturas veros�miles, se deja entender que se llamaba "
88 "Quejana. Pero esto importa poco a nuestro cuento; basta que en la "
89 "narraci�n d�l no se salga un punto de la verdad.";
90
91 /* feed the text into the container */
92
93 word_counter wc;
94 text_tokenizer tok(text,boost::char_separator<char>(" \t\n.,;:!?'\"-"));
95 unsigned int total_occurrences=0;
96 for(text_tokenizer::iterator it=tok.begin(),it_end=tok.end();
97 it!=it_end;++it){
98 /* Insert the word into the container. If duplicate, wit will point to
99 * the preexistent entry.
100 */
101
102 ++total_occurrences;
103 word_counter::iterator wit=wc.insert(*it).first;
104
105 /* Increment occurrences.
106 * In a lambda-capable compiler, this can be written as:
107 * wc.modify_key(wit,++_1);
108 */
109
110 wc.modify_key(wit,increment<unsigned int>());
111 }
112
113 /* list words by frequency of appearance */
114
115 std::cout<<std::fixed<<std::setprecision(2);
116 for(word_counter::iterator wit=wc.begin(),wit_end=wc.end();
117 wit!=wit_end;++wit){
118 std::cout<<std::setw(11)<<wit->word<<": "
119 <<std::setw(5) <<100.0*wit->occurrences/total_occurrences<<"%"
120 <<std::endl;
121 }
122
123 return 0;
124 }
125