如何使用Google Protobuf实现Map结构

11

现在我正在使用Google protobuf并想利用Map结构。但是我发现在Google protobuf中没有实现这样的数据结构。

我的问题很简单。我有一个带有“页码(uint32_t)”和非常简单内容的结构。我想要的是将这个页码作为键,内容作为值。这应该满足空间和速度要求。但是在Protobuf中没有这样的数据结构。

我使用的方法如下:

message MyPageContent {
    required uint32 contentA = 1;
    required uint32 contentB = 2;
}

message MyTable {
    repeated MyPageContent table= 1;
}

我在程序开始时就知道页面的总数。因此,我将所有页面内容添加到表中,并使用一些特殊值(该值用于通知页面不存在,请勿使用该内容)。这样,我可以隐式地使用页面编号进行索引。当页面准备好时,我会更改表中对应的值。人们可以直接使用页面编号作为索引来访问内容。这种方法占用了很多空间(很多页面还没有准备好,我只是放置了一些特殊值来让人们知道它还没有准备好),但访问时间很快。

另一种类似的做法:

message MyTable {
    repeated uint32 pageNum = 1;
    repeated MyPageContent myContent = 2;
}

这样,当页面准备好时,我就可以将一个页面添加到表中。表的大小应该受到限制。然而,人们必须先进行线性搜索,才能找到页面是否在表中。这将消耗很多时间。

基本上,这就是为什么我想在protobuf中使用Map结构。它可以节省空间和时间。

2个回答

27

我不确定这个变化是什么时候发生的,但目前(2015年4月)ProtoBuf 支持 maps

如果想要在数据定义中创建关联映射,协议缓冲提供了一个方便的快捷语法:

map<key_type, value_type> map_field = N;

……其中key_type可以是任何整数或字符串类型(因此除浮点型和bytes外,任何标量类型均可)。value_type可以是任何类型。

例如,如果您想要创建一个项目映射,每个Project消息都与一个string键相关联,可以按如下方式定义它:

map<string,Project> projects = 3;


4
很遗憾,它似乎无法工作,看起来只有文档中支持这个功能。协议编译器不会接受它。 - Lucky Luke
1
“协议编译器不接受它。”听起来你只是安装了旧的protoc。你确定你有最新版本,并且该版本支持ProtoBufV3吗? - Mike Gebirge
1
我该如何在C++中填充地图? - feedc0de
1
@Marco 这是文档中令人困惑的一面。在文档的某些部分中,Proto2 不是指 protobuf v2.x.x。在 proto2/proto3 语法中,maps 在 protobuf v3.x.x 中被原生支持。 - Pradeep Gollakota
1
在这里,“confusing”是关键词 :) 感谢@PradeepGollakota的澄清! - Marco Massenzio
显示剩余2条评论

4

抱歉,这是不可能的。

Protobuf不是一个用于操作数据的库,而是一个用于序列化的库。因此,您可以在std::map或其他容器中操作您的数据,并使用protobuf中的repeated字段进行序列化。


17
这个答案现在已经过时了——protobuf支持maps - Krease

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