|
|
|
|
|
|
|
|
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.