win32 protocol protoc protobuf notes google compiler buffers c++ protocol-buffers

c++ - protocol - protobuf vs json



¿Cómo borrar objetos arbitrarios en campo repetido?(protobuf) (5)

Aquí está el ejemplo:

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; } } }

Tengo algunas entradas en el campo repetido en mi proto. Ahora quiero borrar algunos de ellos. ¿Cómo puedo lograr esto? Hay una función para eliminar el último elemento, pero quiero eliminar elementos arbitrarios. No puedo simplemente cambiarlos porque el orden es importante.

Podría cambiar con el siguiente hasta el final, pero ¿no hay una solución mejor?


Aunque no hay un método directo, puede hacerlo (para mensajes personalizados utilizando la reflexión). El código siguiente elimina el count elementos de campo repetidos a partir del índice de 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); }


De acuerdo con los documentos de la API , no hay una manera de eliminar arbitrariamente un elemento dentro de un campo repetido, solo una forma de eliminar el último.

...
No proporcionamos una forma de eliminar ningún elemento que no sea el anterior porque invita a un uso ineficiente, como los bucles de filtrado O (n ^ 2) que deberían haber sido O (n). Si desea eliminar un elemento que no sea el último, la mejor manera de hacerlo es reorganizar los elementos para que el que desee eliminar esté al final, luego llame a RemoveLast ()
...


Lo que normalmente hago en estos casos es crear un nuevo mensaje Protobuf (PB). Repito los campos repetidos del mensaje existente y los agrego (excepto los que ya no desea) al nuevo mensaje de PB.


Protobuf v2

Puede usar DeleteSubrange(int start, int num) en la clase RepeatedPtrField .

Entonces, si desea eliminar un solo elemento, debe llamar a este método como DeleteSubrange(index_to_be_del, 1) . Se eliminará el elemento en ese índice.

Protobuf v3 update

Como se menciona en los comentarios, el iterator RepeatedField::erase(const_iterator position) puede eliminar en una posición arbitraria