30

I'm currently making a tic-tac-toe program with AI and i'm having a bit of a trouble translating this line of code (python) :

RANKS = dict([(4,3),                       # center  = 3
              (0,2),(2,2),(6,2),(8,2),     # corners = 2
              (1,1),(3,1),(5,1),(7,1)])    # sides   = 1

into C++

any suggestions?

Pradhan
  • 16,391
  • 3
  • 44
  • 59
Jenny Calisay
  • 433
  • 1
  • 4
  • 7

5 Answers5

49

The closest match in C++ would be an std::unordered_map<int, int>. This is a hash table mapping int keys to int values.

#include <unordered_map>


std::unordered_map<int, int> RANKS = {
        { 4, 3 },
        { 0, 2 }, { 2, 2 }, { 6, 2 }, { 8, 2 },
        { 1, 1 }, { 3, 1 }, { 5, 1 }, { 7, 1 }
};

You can access elements using operator[], for example

std::cout << RANKS[0] << std::endl; // prints "2"

Note that the C++ standard library also has the std::map class template, which allows you to create a similar but ordered look-up table std::map<int, int>, with logarithmic look-up and insertion complexity. But python dicts are hash tables, so unordered_map is a closer match in terms of behaviour.

juanchopanza
  • 223,364
  • 34
  • 402
  • 480
  • will it make any difference if i used map instead? – Jenny Calisay Dec 28 '14 at 06:07
  • 5
    @JennyCalisay In this case, the main difference is time complexity. `std::map` is a self-balancing binary search tree, and `std::unordered_map` is a hash table. Look-up is O(log N) vs )(1) respectively, but if you care about performance you should profile code using both. – juanchopanza Dec 28 '14 at 06:10
  • 1
    While this answer was correct in 2014, future readers should note that that since Python 3.6, `dict` are *insertion ordered* (cf. [this Stackoverflow answer](https://stackoverflow.com/questions/39980323/are-dictionaries-ordered-in-python-3-6#answer-39980744)). Thus, since 2017, `std::map` is probably the best answer. – scūriolus Nov 10 '22 at 14:33
  • @scūriolusgodo point. Unfortunately, the ordering is not the same, as `std::map` orders by key, not insertion. I will add a clarification later. – juanchopanza Nov 14 '22 at 08:16
4

You could use a map or unordered_map for this (and they'd work fine) but given that your keys are a dense set of integers (I.e. all the integers from 0 to N) there are better choices.

I'd probably use an std::array instead. It would look something like this:

std::array <char, 9> vals = { 2, 1, 2, 1, 3, 1, 2, 1, 2 };

This gives pretty much the same syntax and observable behavior, but will typically save quite a bit of memory and probably CPU time as well.

Jerry Coffin
  • 476,176
  • 80
  • 629
  • 1,111
2

In C++ this would be a std::unordered_map

#include <unordered_map>

std::unordered_map<int, int> dict
{
    {
        { 4, 3 },
        { 0, 2 }, { 2, 2 }, { 6, 2 }, { 8, 2 },
        { 1, 1 }, { 3, 1 }, { 5, 1 }, { 7, 1 }
    }
};
Marc Dirven
  • 309
  • 2
  • 18
Captain Obvlious
  • 19,754
  • 5
  • 44
  • 74
1

The C++ equivalent of Python's dict is std::map. To initialize a map using a similar syntax, do this:

std::map<int,int> myMap = {{4,3},                       # center  = 3
                           {0,2},{2,2},{6,2},{8,2},     # corners = 2
                           {1,1},{3,1},{5,1},{7,1}};    # sides   = 1

Note that this needs C++11.

If you cannot use C++11, turn to map_list_of in Boost.Assign. The example from their page is:

using namespace boost::assign; // bring 'map_list_of()' into scope
std::map<int,int> next = map_list_of(1,2)(2,3)(3,4)(4,5)(5,6);
Pradhan
  • 16,391
  • 3
  • 44
  • 59
0

Although a "language equivalent" might me something like an std::unordered_map your use case may be more efficiently served with a straight array:

int RANKS[] = {2, 1, 2, 1, 3, 1, 2, 1, 2};
Galik
  • 47,303
  • 4
  • 80
  • 117