2012-11-28 10 views
14

私はprotoの繰り返しフィールドにいくつかのエントリがあります。今私はそれらのいくつかを削除します。どうすればこれを達成できますか?最後の要素を削除する機能がありますが、任意の要素を削除します。順序が重要なので、私はちょうどそれらを交換できません。繰り返しフィールド内の任意のオブジェクトを削除する方法は? (protobuf)

私は次の最後まで交換することができますが、より良い解決策はありませんか?

+0

私はあまりにも愚かですが、あなたの問題をより詳しく説明できますか?どのフレームワーク/ライブラリで作業していますか?ソースコード? – cxxl

+0

ライブラリはgoogleのプロトコルバッファ(protobuf)です。私はここでソースコードが必要ないと思う。反復フィールドは、STLコンテナと同様のデータ所有者です。 – ManuelSchneid3r

+0

protobuf v3のユーザーの場合は、ここに受け入れられた答えを越えてスクロールしてください。https://stackoverflow.com/a/35837227/10278 – pestophagous

答えて

10

API docsによれば、最後のフィールドを削除する方法のように、繰り返しフィールド内から要素を任意に削除する方法はありません。

...
それは非効率的な使用を誘うので、私たちは、このようなOとして、最後の 以外の任意の要素を削除する方法を提供していない(N^2)フィルタリングはO(されている必要があり ループn)。 以外の要素を最後に削除する場合は、削除する要素が最後にあるので、 の要素を並べ替えてから、RemoveLast()を呼び出してください。
...

7

これらのケースで私が通常行うことは、新しいProtobuf(PB)メッセージを作成することです。私は既存のメッセージの繰り返しフィールドを繰り返し、新しいPBメッセージに追加します。

3

いるProtobuf v2の

あなたはDeleteSubrange(int start, int num)RepeatedPtrFieldでクラスを使用することができます。要素をstartインデックスからstart + num - 1インデックスに削除します。

したがって、1つの要素を削除する場合は、このメソッドをDeleteSubrange(index_to_be_del, 1)と呼びます。 index_to_be_deleted + 1 - 1 = index_to_be_delのため、単一の要素が削除されます。これは、@g19fanaticの提案を複製します。

いるProtobuf v3の更新

コメントで述べたように、iterator RepeatedField::erase(const_iterator position)は、任意の位置で

ここ
+0

私は不思議です、なぜ 'erase'を使わないのですか:https:// developers .google.com/protocol-buffers/docs/reference/cpp/google.protobuf.repeated_field#RepeatedField.erase.details – johnbakers

+2

@johnbakersこの時点では、protobuf v3はリリースされていないので、「消去」はv2のプロトタイプではありません。受け入れられた回答には、v2で消去する方法を提供していないことも記載されています。 –

+0

更新された回答 – johnbakers

1

を削除することができます例です:あなたはまだできなくストレートな方法はありませんが

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

これを行う(リフレクションを使用するカスタムメッセージの場合)。以下のコードでは、rowインデックスから始まるフィールド項目が繰り返されるcountが削除されます。

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