2012-11-28 6 views
14

Ich habe einige Einträge in das wiederholte Feld in meinem Proto. Jetzt möchte ich einige von ihnen löschen. Wie kann ich das erreichen? Es gibt eine Funktion, um das letzte Element zu löschen, aber ich möchte beliebige Elemente löschen. Ich kann sie nicht einfach tauschen, weil die Reihenfolge wichtig ist.Wie lösche ich willkürliche Objekte im wiederholten Feld? (protobuf)

Ich könnte mit nächsten bis Ende austauschen, aber gibt es nicht eine bessere Lösung?

+0

Vielleicht bin ich zu dumm, aber können Sie Ihr Problem genauer erklären? Mit welchem ​​Framework/Bibliothek arbeiten Sie? Quellcode? – cxxl

+0

Die Bibliothek ist Protokollpuffer (Protobuf) von Google. Ich denke, ich brauche hier keinen Quellcode. Wiederholte Felder sind Dateninhaber ähnlich den STL-Containern. – ManuelSchneid3r

+0

für Benutzer von Protobuf v3, achten Sie darauf, über die akzeptierte Antwort zu scrollen: https://StackOverflow.com/a/35837227/10278 – pestophagous

Antwort

10

Nach der API docs gibt es keine Möglichkeit, ein Element aus einem wiederholten Feld beliebig zu entfernen, nur eine Möglichkeit, die letzte zu entfernen.

...
Wir bieten keine Möglichkeit, jedes Element außer dem letzten zu entfernen, weil es eine ineffiziente Nutzung lädt, wie beispielsweise O (n^2) Filterschleifen die gewesen O haben sollte (n). Wenn Sie ein anderes Element als das letzte entfernen möchten, ist es am besten, die Elemente neu zu arrangieren, so dass , die Sie entfernen möchten, am Ende ist, dann RemoveLast()
...

aufrufen
7

Normalerweise mache ich in diesen Fällen eine neue Protobuf (PB) -Nachricht. Ich wiederhole die wiederholten Felder der bestehenden Nachricht und füge sie (mit Ausnahme derjenigen, die du nicht mehr willst) zu der neuen PB-Nachricht hinzu.

3

Protobuf v2

Sie können das DeleteSubrange(int start, int num) in RepeatedPtrField Klasse. Es löscht die Elemente aus dem start Index zu start + num - 1 Index. Wenn Sie ein einzelnes Element löschen möchten, müssen Sie diese Methode als DeleteSubrange(index_to_be_del, 1) aufrufen. Es wird das einzelne Element entfernen, da index_to_be_deleted + 1 - 1 = index_to_be_del. Dies repliziert den Vorschlag von @g19fanatic.

Protobuf v3 Update

Wie in den Kommentaren erwähnt, iterator RepeatedField::erase(const_iterator position) an beliebiger Stelle ist hier beispiel

+0

Ich bin neugierig, warum nicht einfach 'löschen': https: // Entwickler verwenden .google.com/protocol-buffers/docs/reference/cpp/google.protobuf.repeated_field # RepeatedField.erase.details – johnbakers

+2

@johnbakers Zu diesem Zeitpunkt ist Protobuf v3 nicht freigegeben, 'Erase' ist nicht in Protobuf v2. Es ist auch in der akzeptierten Antwort erwähnt, dass sie keine Methode zum Löschen in V2 –

+0

Dank für die aktualisierte Antwort bieten – johnbakers

1

löschen:

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

Obwohl es keine Straight-Forward-Methode noch Sie können Tun Sie dies (für benutzerdefinierte Nachricht mit Reflektion). Der folgende Code entfernt count wiederholte Feldelemente beginnend mit row Index.

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