How to delete arbitrary objects in repeated field? (protobuf)

后端 未结 5 1159
广开言路
广开言路 2021-02-18 17:51

I have some entries in the repeated field in my proto. Now I want delete some of them. How can I accomplish this? There is a function to delete the last element, but I want to d

相关标签:
5条回答
  • 2021-02-18 18:22

    Protobuf v2

    You can use the DeleteSubrange(int start, int num) in RepeatedPtrField class.

    If you want to delete a single element then you have to call this method as DeleteSubrange(index_to_be_del, 1). It will remove the element at that index.

    Protobuf v3 update

    As mentioned in the comments, iterator RepeatedField::erase(const_iterator position) can delete at arbitrary position

    0 讨论(0)
  • 2021-02-18 18:24

    Here is example:

    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;
            }
        }
    }
    
    0 讨论(0)
  • 2021-02-18 18:26

    What I usually do in these cases is to create a new Protobuf (PB) message. I iterate the repeated fields of the existing message and add them (except the ones you don't want anymore) to the new PB message.

    0 讨论(0)
  • 2021-02-18 18:27

    According to the API docs, there isn't a way to arbitrarily remove an element from within a repeated field, just a way to remove the last one.

    ...
    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()
    ...

    0 讨论(0)
  • 2021-02-18 18:36

    Although there's no straight-forward method you still can do this (for custom message using reflection). Code below removes count repeated field items starting from row index.

    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);
    }
    
    0 讨论(0)
提交回复
热议问题