23

我在原型的重复字段中有一些条目。现在我想删除其中的一些。我怎样才能做到这一点?有删除最后一个元素的功能,但我想删除任意元素。我不能只是交换它们,因为顺序很重要。

我可以与 next 交换直到结束,但没有更好的解决方案吗?

4

5 回答 5

17

对于 Protobuf v3

iterator RepeatedField::erase(const_iterator position)可以在任意位置删除。

对于 Protobuf v2

你可以DeleteSubrange(int start, int num)RepeatedPtrField课堂上使用。

如果要删除单个元素,则必须将此方法称为DeleteSubrange(index_to_be_del, 1). 它将删除该索引处的元素。

于 2016-03-07T06:07:57.670 回答
15

根据API docs,没有办法从重复字段中任意删除元素,只是删除最后一个元素的方法。

...
我们不提供删除除最后一个元素之外的任何元素的方法,因为它会导致使用效率低下,例如 O(n^2) 过滤循环应该是 O(n)。如果要删除除最后一个以外的元素,最好的方法是重新排列元素,使要删除的元素位于末尾,然后调用 RemoveLast()
...

于 2012-12-06T14:39:42.443 回答
8

在这些情况下,我通常会创建一个新的 Protobuf (PB) 消息。我迭代现有消息的重复字段并将它们(您不再需要的除外)添加到新的 PB 消息中。

于 2013-11-11T22:01:18.000 回答
0

这是示例:

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;
        }
    }
}
于 2016-03-16T10:31:19.947 回答
0

尽管没有直接的方法,但您仍然可以这样做(对于使用反射的自定义消息)。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);
}
于 2016-08-16T01:20:58.853 回答