2012-11-28 21 views
14

मेरे प्रोटो में दोहराए गए क्षेत्र में कुछ प्रविष्टियां हैं I अब मैं उनमें से कुछ को हटाना चाहता हूं। मैं यह कैसे हासिल कर सकता हूं? अंतिम तत्व को हटाने के लिए एक फ़ंक्शन है, लेकिन मैं मनमानी तत्वों को हटाना चाहता हूं। मैं सिर्फ उन्हें स्वैप नहीं कर सकता क्योंकि आदेश महत्वपूर्ण है।दोहराए गए क्षेत्र में मनमानी वस्तुओं को कैसे हटाएं? (प्रोटोबफ)

मैं अंत तक अगले के साथ स्वैप कर सकता हूं, लेकिन क्या कोई अच्छा समाधान नहीं है?

+0

शायद मैं बहुत बेवकूफ हूं, लेकिन क्या आप अपनी समस्या को और विस्तार से समझा सकते हैं? आप किस ढांचे/पुस्तकालय के साथ काम कर रहे हैं? सोर्स कोड? – cxxl

+0

लाइब्रेरी Google से प्रोटोकॉल बफर (प्रोटोबफ) है। मुझे लगता है मुझे यहां स्रोत कोड की आवश्यकता नहीं है। दोहराए गए क्षेत्र एसटीएल कंटेनरों के समान डेटाहोल्डर्स हैं। Protobuf v3 के उपयोगकर्ताओं के लिए – ManuelSchneid3r

+0

, यहां स्वीकृत उत्तर से परे स्क्रॉल करना सुनिश्चित करें: https://stackoverflow.com/a/35837227/10278 – pestophagous

उत्तर

10

API docs के मुताबिक, दोहराए गए क्षेत्र में से किसी तत्व को मनमाने ढंग से निकालने का कोई तरीका नहीं है, केवल अंतिम को हटाने का एक तरीका है।

...
हम क्योंकि यह इतना हे के रूप में अकुशल प्रयोग, आमंत्रित किया है किसी भी पिछले के अलावा अन्य तत्व को दूर करने के लिए एक रास्ता प्रदान नहीं करते हैं (एन^2) छानने लूप हे कि किया जाना चाहिए था (एन)। यदि आप आखिरी की तुलना में अन्य तत्व को निकालना चाहते हैं, तो इसे करने का सबसे अच्छा तरीका तत्वों को फिर से व्यवस्थित करना है ताकि जिसे आप निकालना चाहते हैं, अंत में है, तो RemoveLast()
पर कॉल करें ...

7

मैं इन मामलों में आमतौर पर क्या करता हूं वह एक नया प्रोटोबफ (पीबी) संदेश बनाना है। मैं मौजूदा संदेश के बार-बार फ़ील्ड को पुन: सक्रिय करता हूं और उन्हें नए पीबी संदेश में जोड़ता हूं (जिन्हें आप अब और नहीं चाहते हैं)।

3

Protobuf v2

आप DeleteSubrange(int start, int num)RepeatedPtrField कक्षा में उपयोग कर सकते हैं। यह start अनुक्रमणिका से start + num - 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

मैं उत्सुक हूं, क्यों न केवल 'मिटाएं' का उपयोग करें: https: // डेवलपर .google.com/प्रोटोकॉल-बफर/दस्तावेज़/संदर्भ/सीपीपी/google.protobuf.repeated_field # RepeatedField.erase.details – johnbakers

+2

@johnbakers उस समय protobuf v3 जारी नहीं किया गया है, 'erase' protobuf 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); 
} 
संबंधित मुद्दे