How to delete arbitrary objects in repeated field? (protobuf)
我的原型中的重复字段中有一些条目。 现在我要删除其中一些。 我该怎么做? 有一个删除最后一个元素的功能,但是我想删除任意元素。 我不能只交换它们,因为顺序很重要。
我可以与下一个交换直到结束,但是没有更好的解决方案吗?
Protobuf v2
您可以在
如果要删除单个元素,则必须将此方法称为
Protobuf v3更新
如评论中所述,
根据API文档,没有一种方法可以从重复字段中任意删除一个元素,而只是删除最后一个元素。
...
We don't provide a way to remove any element other than the last
because it invites inefficient use, such as O(n^2) filtering loops
that should have been O(n). If you want to remove an element other
than the last, the best way to do it is to re-arrange the elements so
that the one you want removed is at the end, then call RemoveLast()
...
在这些情况下,我通常要做的是创建新的Protobuf(PB)消息。 我迭代现有消息的重复字段,并将它们(除了您不再想要的字段除外)添加到新的PB消息中。
这是示例:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 | message GuiChild { optional string widgetName = 1; //.. } message GuiLayout { repeated ChildGuiElement children = 1; //.. } typedef google_public::protobuf::RepeatedPtrField<GuiChild> RepeatedField; typedef google_public::protobuf::Message Msg; GuiLayout guiLayout; //Init children as necessary.. GuiChild child; //Set child fileds.. DeleteElementsFromRepeatedField(*child, guiLayout->mutable_children()); void DeleteElementsFromRepeatedField(const Msg& msg, RepeatedField* repeatedField) { for (RepeatedField::iterator it = repeatedField->begin(); it != repeatedField->end(); it++) { if (google_public::protobuf::util::MessageDifferencer::Equals(*it, msg)) { repeatedField->erase(it); break; } } } |
尽管没有简单的方法,您仍然可以执行此操作(对于使用反射的自定义消息)。 下面的代码删除从
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | void RemoveFromRepeatedField( const google::protobuf::Reflection *reflection, const google::protobuf::FieldDescriptor *field, google::protobuf::Message *message, int row, int count) { int size = reflection->FieldSize(*message, field); // shift all remaining elements for (int i = row; i < size - count; ++i) reflection->SwapElements(message, field, i, i + count); // delete elements from reflection for (int i = 0; i < count; ++i) reflection->RemoveLast(message, field); } |