简体   繁体   中英

Can we make a map in C++, with the value as a function of key?

In C++ STL, the map is used to map the key to a value. I want to know whether we can do this mapping based on some function say

map< int, string > M;
and value=binary_representation(key) ?

You can insert arbitrary ( key , value ) pairs into a std::map so you can certainly insert ( x i , f ( x i )) pairs for a function f and any x 1 , …, x n you like, provided that the types match.

The straight-forward way to do this might be to use a for loop.

for (const auto& k : keys)
  mapping[k] = f(k);

Here is a complete example:

#include <climits>
#include <iomanip>
#include <iostream>
#include <map>
#include <string>

namespace /* anonymous */
{

  std::string
  my_function(const int n)
  {
    const auto size = static_cast<int>(CHAR_BIT * sizeof(int));
    std::string bits {};
    for (auto i = 0; i < size; ++i)
      {
        const auto bit = (n >> (size - i - 1)) & 1;
        bits += (bit ? '1' : '0');
      }
    return bits;
  }

}


int
main()
{
  std::map<int, std::string> reprs {};
  for (auto k = -3; k < 10; ++k)
    reprs[k] = my_function(k);
  for (const auto& kv : reprs)
    std::cout << std::setw(4) << kv.first << "  =>  " << kv.second << '\n';
}

Possible output:

  -3  =>  11111111111111111111111111111101
  -2  =>  11111111111111111111111111111110
  -1  =>  11111111111111111111111111111111
   0  =>  00000000000000000000000000000000
   1  =>  00000000000000000000000000000001
   2  =>  00000000000000000000000000000010
   3  =>  00000000000000000000000000000011
   4  =>  00000000000000000000000000000100
   5  =>  00000000000000000000000000000101
   6  =>  00000000000000000000000000000110
   7  =>  00000000000000000000000000000111
   8  =>  00000000000000000000000000001000
   9  =>  00000000000000000000000000001001

If you want to follow the advice of favoring algorithms over raw loops, you could use std::transform together with a std::insert_iterator to do the trick.

#include <algorithm>
#include <iomanip>
#include <iostream>
#include <iterator>
#include <map>
#include <string>
#include <utility>
#include <vector>

namespace /* anonymous */
{

  std::string
  my_function(int);  // as above

}

int
main()
{
  std::vector<int> keys(13);
  std::iota(keys.begin(), keys.end(), -3);
  std::map<int, std::string> reprs {};
  const auto generator = [](const int n){
    return std::make_pair(n, my_function(n));
  };
  std::transform(keys.cbegin(), keys.cend(),
                 std::inserter(reprs, reprs.begin()),
                 generator);
  for (const auto& kv : reprs)
    std::cout << std::setw(4) << kv.first << "  =>  " << kv.second << '\n';
}

However, I'm not sure if the use of iterators and algorithms really helps the readability of the code in this simple case. The use of the keys vector is a bit of an abomination here. If you have Boost, you could replace it by a boost::counting_iterator .

You could do, but it would be completely pointless. It would just be an inferior std::set<int> that doesn't properly guarantee the invariant and consumes a higher memory usage and runtime for absolutely no benefit whatsoever (unless you really wanted a cache).

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM