将 Python 字典转换为 C++

26
我有一段包含以下代码的Python程序。
d = {}

d[(0,0)] = 0
d[(1,2)] = 1
d[(2,1)] = 2
d[(2,3)] = 3
d[(3,2)] = 4

for (i,j) in d:
    print d[(i,j)], d[(j,i)]

很遗憾,在Python中循环所有键并不够快,我想将这段代码翻译成C++。对于一个以元组为键的Python字典,最好使用哪种C++数据结构?与上面的代码相当的C++代码是什么?

我查看了Boost库中的稀疏矩阵,但找不到仅循环非零元素的简单方法。


你是否考虑过另一种数据布局。如果(i,j)总是与(j,i)配对,那么你可能不需要两者都存储。你可以在构建字典的同时建立关联。你可以只存储(i,j)的字典条目,存储为(d(i,j), d(j,i))。这假设元组中的数字可以任意排序,这可能是正确的。 - Sanjaya R
此外,如果你只是遍历元组,请将它们存储在一个列表中并遍历该列表。 - Sanjaya R
7个回答

41

在C++中,词典可以用std::map表示,而包含两个元素的元组则可以用std::pair。

提供的Python代码可翻译为:

#include <iostream>
#include <map>

typedef std::map<std::pair<int, int>, int> Dict;
typedef Dict::const_iterator It;

int main()
{
   Dict d;

   d[std::make_pair(0, 0)] = 0;
   d[std::make_pair(1, 2)] = 1;
   d[std::make_pair(2, 1)] = 2;
   d[std::make_pair(2, 3)] = 3;
   d[std::make_pair(3, 2)] = 4;

   for (It it(d.begin()); it != d.end(); ++it)
   {
      int i(it->first.first);
      int j(it->first.second);
      std::cout <<it->second <<' '
                <<d[std::make_pair(j, i)] <<'\n';
   }
}

2
非常好,干得好。对于像我这样从老派C++升级到现代C++的人来说非常有教育意义。 - Bill Forster
1
d[*it] 应该改为 it->second - Roger Pate
2
似乎错误是由joshperry的编辑引入的。 - chollida
请注意,使用C++14,std::make_pair(a, b)可以被简单地写成{a, b},这使得代码看起来更加简洁。 - Romeo Valentin

8
类型是:
std::map< std::pair<int,int>, int>

添加条目到地图的代码如下:

typedef  std::map< std::pair<int,int>, int> container;

container m;

m[ make_pair(1,2) ] = 3; //...

for(container::iterator i = m.begin();  i != m.end(); ++i){
   std::cout << i.second << ' '; 
   // not really sure how to translate [i,j] [j,i] idiom here easily
}

1
当类型不是一个相关名称时,您不能使用“typename”。 - Roger Pate
@Roger:你说得对,修正了“typename container::iterator”。 - catwalk

5

请参考Boost.python。这是用于Python和C++之间交互的工具(基本上是使用C++构建Python库,还可将Python嵌入C++程序中)。其中描述了大多数Python数据结构及其对应的C++实现(未检查是否包含所需内容)。


3

std::map或者更可能是std::tr1::unordered_map / boost::unordered_map(也称为hash_map)是您想要的。

另外,正如kriss所说,Boost.Python在这里是一个不错的选择。它已经提供了Python字典类的C++版本,因此如果您正在进行跨语言操作,它可能非常有用。


2

通常情况下,Map 被实现为平衡二叉树而非哈希表。但 Python 字典不是这种情况。因此,你需要一个 C++ O(1) 等效的数据结构来使用你的键值对。


1

你想通过Python调用优化的C++例程吗? 如果是,请继续阅读:

通常我在处理Python中的字典时使用PyYaml。 也许你可以链接一些像LibYAMLyamlcpp这样的东西来:

  1. 将Python字典转换为YAML字符串
  2. 使用Python调用使用类似SWIG包装的C ++函数,以YAML字符串作为参数。
  3. 使用C ++库解析YAML并获得std :: map对象
  4. 操作std :: map对象

警告:我从未尝试过这种方法,但在“yaml std :: map”上使用每个人最喜欢的搜索引擎会产生许多有趣的链接


0

作为对你问题的直接回答(关于Python部分请看我的其他回答)。如果你愿意,可以忘记元组部分。在C++中,你可以使用任何映射类型的键/值(哈希等),只需要找到一个唯一的键函数即可。在某些情况下,这可能很容易。例如,如果你有两个整数是介于1和65536之间的整数,你可以使用一个32位整数,每个16位部分都是其中一个键。一个简单的移位和“或”或+来组合两个值就可以解决问题,而且非常高效。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接