Comment supprimer des objects arbitraires dans un champ répété? (protobuf)

J’ai quelques entrées dans le champ répété dans mon proto. Maintenant, je veux supprimer certains d’entre eux. Comment puis-je accomplir cela? Il existe une fonction pour supprimer le dernier élément, mais je veux supprimer des éléments arbitraires. Je ne peux pas simplement les échanger car l’ordre est important.

Je pourrais échanger avec jusqu’à la fin, mais n’y a-t-il pas une solution plus intéressante?

Selon la documentation de l’ API , il n’est pas possible de supprimer arbitrairement un élément d’un champ répété, mais simplement de supprimer le dernier.


Nous ne fournissons pas un moyen de supprimer un élément autre que le dernier, car il invite à une utilisation inefficace, telle que les boucles de filtrage O (n ^ 2) qui auraient dû être O (n). Si vous souhaitez supprimer un élément autre que le dernier, la meilleure façon de le faire est de réorganiser les éléments afin que celui que vous souhaitez supprimer soit à la fin, puis appelez RemoveLast ().

Protobuf v2

Vous pouvez utiliser DeleteSubrange(int start, int num) dans la classe RepeatedPtrField .

Donc, si vous voulez supprimer un seul élément, vous devez appeler cette méthode comme DeleteSubrange(index_to_be_del, 1) . Cela supprimera l’élément à cet index.

Mise à jour de Protobuf v3

Comme mentionné dans les commentaires, l’ iterator RepeatedField::erase(const_iterator position) peut supprimer à une position arbitraire

Ce que je fais habituellement dans ces cas-là est de créer un nouveau message Protobuf (PB). J’itère les champs répétés du message existant et les ajoute (sauf ceux que vous ne voulez plus) au nouveau message PB.

Voici un exemple:

 message GuiChild { optional ssortingng widgetName = 1; //.. } message GuiLayout { repeated ChildGuiElement children = 1; //.. } typedef google_public::protobuf::RepeatedPtrField 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; } } } 

Bien qu’il n’y ait pas de méthode simple, vous pouvez toujours le faire (pour un message personnalisé utilisant la reflection). Le code ci-dessous supprime le count éléments de champs répétés à partir de l’index 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); }