C++ 如何删除重复字段中的任意对象?(protobuf)
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/13603878/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How to delete arbitrary objects in repeated field? (protobuf)
提问by ManuelSchneid3r
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 delete arbitrary elements. I cant just swap them because the order is important.
我的原型的重复字段中有一些条目。现在我想删除其中一些。我怎样才能做到这一点?有删除最后一个元素的功能,但是我想删除任意元素。我不能只是交换它们,因为顺序很重要。
I could swap with next until end, but isn't there a nicer solution?
我可以与 next 交换直到结束,但没有更好的解决方案吗?
采纳答案by g19fanatic
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.
根据API 文档,没有办法从重复字段中任意删除元素,只能删除最后一个元素。
...
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()
...
...
我们不提供删除除最后一个元素之外的任何元素的方法,因为它会导致使用效率低下,例如 O(n^2) 过滤循环本应为 O(n)。如果要删除最后一个元素以外的元素,最好的方法是重新排列元素,使要删除的元素位于最后,然后调用 RemoveLast()
...
回答by jblixr
Protobuf v2
Protobuf v2
You can use the DeleteSubrange(int start, int num)
in RepeatedPtrField
class.
你可以DeleteSubrange(int start, int num)
在RepeatedPtrField
课堂上使用。
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.
如果要删除单个元素,则必须将此方法调用为DeleteSubrange(index_to_be_del, 1)
. 它将删除该索引处的元素。
Protobuf v3 update
Protobuf v3 更新
As mentioned in the comments, iterator RepeatedField::erase(const_iterator position)
can delete at arbitrary position
如评论中所述,iterator RepeatedField::erase(const_iterator position)
可以在任意位置删除
回答by jard18
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.
在这些情况下,我通常做的是创建一个新的 Protobuf (PB) 消息。我迭代现有消息的重复字段并将它们(除了您不再需要的那些)添加到新的 PB 消息中。
回答by user3455965
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;
}
}
}
回答by Vyacheslav Napadovsky
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.
尽管没有直接的方法,您仍然可以执行此操作(对于使用反射的自定义消息)。下面的代码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);
}