2012-11-28 14 views
14

Ho alcune voci nel campo ripetuto nel mio proto. Ora voglio cancellarne alcuni. Come posso realizzare questo? C'è una funzione per cancellare l'ultimo elemento, ma voglio eliminare elementi arbitrari. Non riesco a scambiarli perché l'ordine è importante.Come eliminare oggetti arbitrari nel campo ripetuto? (protobuf)

Potrei scambiare con il prossimo fino alla fine, ma non c'è una soluzione migliore?

+0

Forse sono troppo stupido, ma puoi spiegare il tuo problema in modo più dettagliato? Con che struttura/libreria stai lavorando? Codice sorgente? – cxxl

+0

La libreria è buffer di protocollo (protobuf) di google. Immagino di non aver bisogno del codice sorgente qui. I campi ripetuti sono dati simili ai contenitori STL. – ManuelSchneid3r

+0

per gli utenti di protobuf v3, assicurati di scorrere oltre la risposta accettata a qui: https://stackoverflow.com/a/35837227/10278 – pestophagous

risposta

10

Secondo lo API docs, non esiste un modo per rimuovere arbitrariamente un elemento all'interno di un campo ripetuto, solo un modo per rimuovere l'ultimo.

...
Noi non forniscono un modo per rimuovere qualsiasi elemento diverso dall'ultimo perché invita uso inefficiente, come O (n^2) di filtro loop che avrebbe dovuto essere O (n). Se si desidera rimuovere un elemento diverso da rispetto all'ultimo, il modo migliore per farlo è riorganizzare gli elementi in modo da che quello che si desidera rimuovere è alla fine, quindi chiamare RemoveLast()
...

7

Quello che faccio di solito in questi casi è creare un nuovo messaggio Protobuf (PB). Itero i campi ripetuti del messaggio esistente e li aggiungo (eccetto quelli che non vuoi più) al nuovo messaggio PB.

3

Protobuf v2

È possibile utilizzare la DeleteSubrange(int start, int num) in RepeatedPtrField classe. Elimina gli elementi dall'indice start all'indice start + num - 1.

Quindi, se si desidera eliminare un singolo elemento, è necessario chiamare questo metodo come DeleteSubrange(index_to_be_del, 1). Rimuoverà il singolo elemento perché index_to_be_deleted + 1 - 1 = index_to_be_del. Questo replicherà il suggerimento di @g19fanatic.

Protobuf v3 aggiornamento

Come accennato nei commenti, iterator RepeatedField::erase(const_iterator position) possibile eliminare in posizione arbitraria

+0

sono curioso, perché non usare solo 'cancella': https: // sviluppatori .google.com/protocol-buffer/docs/reference/cpp/google.protobuf.repeated_field # RepeatedField.erase.details – johnbakers

+2

@johnbakers In quel momento protobuf v3 non è stato rilasciato, 'erase' non è in protobuf v2. Si è anche accennato nella risposta accettata che non hanno fornito alcun metodo per cancellare in v2 –

+0

grazie per la risposta aggiornata – johnbakers

1

Ecco esempio:

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

anche se non c'è alcun metodo straight-forward è ancora possibile fai questo (per messaggi personalizzati usando la riflessione). Il codice sottostante rimuove gli articoli di campo ripetuti count a partire dall'indice 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); 
} 
Problemi correlati