|
|
|
|
|
|
|
|
COBBLESTONE: 5 IRON_INGOT: 3 OAK_PLANK: 4 REDSTONE: 2 |
But now, since this code has buzzed in my mind for hours, I can’t help asking you: since you don’t modify the original argument, why don’t you pass it by const reference? |
JLBorges wrote: |
---|
Use a normal std::map with the key as the item and the mapped value as the count of items. |
JLBorges wrote: | ||
---|---|---|
For example:
http://coliru.stacked-crooked.com/a/08af40463c79e9cc |
for( unsigned char c : str ) if( !std::isspace(c) ) key += std::toupper(c) ;
does unsigned char just mean it takes up less space than a normal char? I read: https://stackoverflow.com/questions/75191/what-is-an-unsigned-char but I don't fully understand what it means.
|
|
void make_map(std::istream &stm, std::map<std::string, int> &map)
? So the map itself would always be updated in main() without returning anything. Otherwise it has to make a map in the make_map() function & in main() which would be more costly (I think).
|
|
while( stm >> item )
part means it goes through every line in the file and stores the info into item
variable until EOF has been reached and it ends the loop, correct?++map[make_key(item)]
while( stm >> item )
acts like std::cin (I think) so it only takes the characters until the next white space and skips the white space. In other words, there is no white space to remove, right?JLBorges wrote: |
---|
It is indeed redundant for this specific example (where the spaces are already skipped by formatted input). |
const auto map = make_map(file) ;
for( const auto& [key,cnt] : map ) std::cout << std::quoted(key) << " - " << cnt << '\n' ;
for( const auto& [key,cnt] : map ) std::cout << std::quoted(key) << " - " << cnt << '\n' ;
JLBorges wrote: |
---|
> Would I only use unordered maps if I had thousands, or millions, of keys/values to store > and didn't need for them to be in a specific order? In general, for large data sets, unordered map gives better average insertion and look up performance. However, with unordered maps, the memory usage tends to be higher; its worst case performance may be an issue (that is: even though average performance is much better, a specific insertion or look up may be worse than the guaranteed logarithmic performance for a map). As a general rule, favour unordered map for large data sets. > In for( unsigned char c : str ) if( !std::isspace(c) ) key += std::toupper(c) ; > does unsigned char just mean it takes up less space than a normal char? No. Both char and unsigned char have he same size. The reason for using unsigned char: https://en.cppreference.com/w/cpp/string/byte/toupper#Notes > Wouldn't it make more sense to have a void function that has a function parameter of the map passed by reference. There are two reasons why passing a map by reference would not be more efficient: a. Named Return Value Optimisation (NRVO) https://en.cppreference.com/w/cpp/language/copy_elision b. Even if, for some reason, the optimisation (NRVO) can't be applied, the map object would be moved (cheap) rather than copied (expensive). > For the code: ++map[make_key(item)] make_key(item) makes the key (strips hite space, convert to upper case). Once the key is made, there are two possibilities: a. This key does not exist in the map. In this case, a new key-value pair is inserted into the map, with the mapped value initialised to zero. The ++ part increments the mapped value (from zero to one); in the end we have the key in the map with an associated value of one. a. This key already exists in the map. In this case, we get a reference to the value assopciated with the key; The ++ part increments that value (if the count was 6 earlier, it now becomes 7). > for( const auto& [key,cnt] : map ) Structured binding (C++17): http://www.nuonsoft.com/blog/2017/07/26/c17-structured-bindings/ |
lastchance wrote: | ||
---|---|---|
|
for ( string s; in >> s; ) freq[toupper(s)]++;
for ( auto p : freq ) cout << p.first << ": " << p.second << '\n';
auto x = expr;
. The type is deduced from the initializer.