我在原型的重复字段中有一些条目。现在我想删除其中的一些。我怎样才能做到这一点?有删除最后一个元素的功能,但我想删除任意元素。我不能只是交换它们,因为顺序很重要。
我可以与 next 交换直到结束,但没有更好的解决方案吗?
我在原型的重复字段中有一些条目。现在我想删除其中的一些。我怎样才能做到这一点?有删除最后一个元素的功能,但我想删除任意元素。我不能只是交换它们,因为顺序很重要。
我可以与 next 交换直到结束,但没有更好的解决方案吗?
对于 Protobuf v3
iterator RepeatedField::erase(const_iterator position)
可以在任意位置删除。
对于 Protobuf v2
你可以DeleteSubrange(int start, int num)
在RepeatedPtrField
课堂上使用。
如果要删除单个元素,则必须将此方法称为DeleteSubrange(index_to_be_del, 1)
. 它将删除该索引处的元素。
根据API docs,没有办法从重复字段中任意删除元素,只是删除最后一个元素的方法。
...
我们不提供删除除最后一个元素之外的任何元素的方法,因为它会导致使用效率低下,例如 O(n^2) 过滤循环应该是 O(n)。如果要删除除最后一个以外的元素,最好的方法是重新排列元素,使要删除的元素位于末尾,然后调用 RemoveLast()
...
在这些情况下,我通常会创建一个新的 Protobuf (PB) 消息。我迭代现有消息的重复字段并将它们(您不再需要的除外)添加到新的 PB 消息中。
这是示例:
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;
}
}
}
尽管没有直接的方法,但您仍然可以这样做(对于使用反射的自定义消息)。count
下面的代码从row
索引开始删除重复的字段项。
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);
}