C++ Loop through first K elements of unordered_map

I have an unordered_map that stores counts of integers. I want to loop through the map, but instead of fetching all the entries, I only wish to get the first K.It is guaranteed that map has more than K entries.

I'm running into issues when I do the following:

  unordered_map<int, int> u_map;
  // Logic to populate the map
  
  for(auto it=u_map.begin(); it!=u_map.begin()+2; it++)
  cout<<it->first<<" "<<it->second<<endl;

The expression u_map.begin()+2 is causing the issue.

So is it possible to get only the first K entries of a map using for_each loop in C++?

2 answers

  • answered 2021-11-25 04:57 Anoop Rana

    I only wish to get the first K

    Note from std::unordered_map documentation

    an unordered_map object makes no guarantees on which specific element is considered its first element.

    This essentially means that there is no guarantee that you will iterate over the elements in the inserted order.

    For iterating over the elements of the map you can use:

    int count  = 0;
    for (auto& it: u_map) {
        /* some code here like you can keep a count variable that will check if it 
        reaches the number K and then break the loop. But remember that it is 
        **not** guaranteed that the elements you will get will be in inserted order.*/
       
       if(count < K)
       {
        cout<<it.first<<" "<<it.second<<endl;
       }
       else 
       {
          break;
       }
       ++count;
    }
    

    Working example

    #include <iostream>
    #include <unordered_map>
    using namespace std;
    int main()
    {
    std::unordered_map<std::string, std::string> u_map = {
            {"RED","#FF0000"},
            {"GREEN","#00FF00"},
            {"BLUE","#0000FF"},{"PURPLE","#0F00FF"},{"WHITE","#0000RF"},{"ORANGE","#F000FF"}
        };
       int K = 3; 
       int count  = 0;
       for (auto& it: u_map) 
       {
           if(count < K)
           {
                cout<<it.first<<" "<<it.second<<endl;
           }
           else 
           {
                break;
            }
            ++count;
        }
    return 0;
    }
    

  • answered 2021-11-25 05:02 康桓瑋

    If you can use C++20, then views::take would be a choice.

    #include <unordered_map>
    #include <ranges>
    #include <iostream>
    
    int main() {
      std::unordered_map<int, int> u_map;
      for (auto [key, value] : u_map | std::views::take(2))
        std::cout << key << " " << value << "\n";
    }
    

    Alternative for pre-C++20:

    std::unordered_map<int, int> u_map;
    auto end = std::next(u_map.begin(), 2);
    for (auto it = u_map.begin(); it != end; ++it)
      std::cout << it->first << " " << it->second << "\n";
    

How many English words
do you know?
Test your English vocabulary size, and measure
how many words do you know
Online Test
Powered by Examplum