プロトの繰り返しフィールドにいくつかのエントリがあります。今、それらのいくつかを削除したいと思います。どうすればこれを達成できますか? 最後の要素を削除する機能がありますが、任意の要素を削除したいです。順序が重要なので、単に交換することはできません。
最後まで next と交換できますが、もっと良い解決策はありませんか?
プロトの繰り返しフィールドにいくつかのエントリがあります。今、それらのいくつかを削除したいと思います。どうすればこれを達成できますか? 最後の要素を削除する機能がありますが、任意の要素を削除したいです。順序が重要なので、単に交換することはできません。
最後まで next と交換できますが、もっと良い解決策はありませんか?
Protobuf v3 の場合
iterator RepeatedField::erase(const_iterator position)
任意の位置で削除できます。
Protobuf v2 の場合
DeleteSubrange(int start, int num)
インRepeatedPtrField
クラスで使えます。
単一の要素を削除する場合は、このメソッドを として呼び出す必要がありますDeleteSubrange(index_to_be_del, 1)
。そのインデックスの要素を削除します。
APIドキュメントによると、繰り返されるフィールド内から要素を任意に削除する方法はなく、最後の要素を削除する方法があります。
...
O(n)であるはずのO(n ^ 2)フィルタリングループなど、非効率的な使用を招くため、最後の要素以外の要素を削除する方法は提供していません。最後以外の要素を削除する場合は、削除する要素が最後になるように要素を再配置してから、RemoveLast()を呼び出すのが最善の方法
です...
次に例を示します。
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;
}
}
}
簡単な方法はありませんが、これを行うことができます (リフレクションを使用したカスタム メッセージの場合)。以下のコードは、インデックス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);
}