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