2012-11-28 19 views
14

Protokolümde tekrarlanan alanda bazı girişler var. Şimdi bunların bir kısmını silmek istiyorum. Bunu nasıl başarabilirim? Son unsuru silmek için bir fonksiyon var, fakat keyfi öğeleri silmek istiyorum. Onları takas edemem çünkü sipariş önemli.Yinelenen alanda rasgele nesneler nasıl silinir? (protobuf)

Yandaki ile takas edebilirim, ama daha hoş bir çözüm yok mu?

+0

Belki de çok aptalım, ama sorununuzu daha ayrıntılı olarak açıklayabilir misiniz? Hangi çerçeve/kütüphane ile çalışıyorsunuz? Kaynak kodu? – cxxl

+0

Kütüphane, google'dan protokol tamponlarıdır (protobuf). Sanırım burada kaynak koduna ihtiyacım yok. Tekrarlanan alanlar STL konteynırlarına benzer veri sahipleridir. Protobuf v3 kullanıcıları için – ManuelSchneid3r

+0

, kabul edilen cevabın ötesine ilerlediğinizden emin olun: https://stackoverflow.com/a/35837227/10278 – pestophagous

cevap

10

API docs'a göre, bir öğeyi, sonuncuyu kaldırmak için bir yoldan tekrarlanan bir alanın içinden keyfi olarak kaldırmanın bir yolu yoktur. Biz böyle O olarak verimsiz kullanımı, davet çünkü son dışında herhangi elemanını kaldırmak için bir yol vermeyin

... (n^2) filtreleme olmalıydı O (döngüler n). Eğer öncekinden daha başka bir öğe kaldırmak istiyorsanız, bunu yapmanın en iyi yolu böylece Kaldırılmasını istediğiniz bir ucunda olduğunu, daha sonra çağrı parçasını yeniden düzenlemek için RemoveLast()
...

olduğunu
7

Genellikle bu durumlarda yaptığım şey yeni bir Protobuf (PB) mesajı oluşturmaktır. Mevcut mesajın tekrarlanan alanlarını yineliyorum ve onları (artık istemediğiniz olanlar hariç) yeni PB mesajına ekleyin.

3

Protobuf v2

Sen DeleteSubrange(int start, int num) sınıf RepeatedPtrField kullanabilirsiniz. start dizinindeki öğeleri start + num - 1 dizinine siler.

Tek bir öğeyi silmek isterseniz, bu yöntemi DeleteSubrange(index_to_be_del, 1) olarak çağırmanız gerekir. Tek elemanı kaldıracaktır çünkü index_to_be_deleted + 1 - 1 = index_to_be_del. Bu, @g19fanatic önerisini çoğaltacaktır.

yorum belirtildiği gibi

, iterator RepeatedField::erase(const_iterator position) keyfi pozisyona İşte

+0

Merak ediyorum, neden sadece "silme" kullanmayın: https: // geliştiriciler .google.com/protocol-buffers/docs/reference/cpp/google.protobuf.repeated_field # RepeatedField.erase.details – johnbakers

+2

@johnbakers O zaman protobuf v3 serbest bırakılmaz, "silme" protobuf v2'de değildir. Ayrıca, kabul edilen cevapta, güncellenmiş cevap için v2 –

+0

'da silme yöntemini sağlamadıkları belirtilmiştir. – johnbakers

1

de silebilirsiniz Protobuf v3 güncelleme örnektir: hayır düz ileri bir yöntem var hala edebilirsiniz olsa

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

Bunu yapın (yansımayı kullanarak özel mesaj için). Aşağıdaki kod, row dizininden başlayarak count tekrarlanan alan öğelerini kaldırır.

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