简体   繁体   中英

protobuf: RepeatedField unique elements

I want to have in a google protocol buffer repeated field only unique elements. In other words, need to use it as a std::set instead of std::vector .

Any idea which is the simplest and most efficient way to do that?

EDIT : I wouldn't want to use any iterators to loop through all the elements if possible.

Ok, as the comments from the question stated, there isn't any way of doing this without using iterators. However, maybe someone else is interested in this, here is the function i coded to achieve this. This will take as parameters a RepeatedPtrField< T >* (the list) and a std::string (key of the new object that we intend to add to the list) and will return the element that matches the id, or NULL if there isn't any entry with this key in the RepeatedField list.

This way, you can easy keep a list of unique elements directly in a RepeatedField without using any other std structure:

template <class T>
T* repeatedFieldLookup( google::protobuf::RepeatedPtrField< T >* repeatedPtrField, std::string id)
{
   google::protobuf::internal::RepeatedPtrOverPtrsIterator<T> it = repeatedPtrField->pointer_begin();
   for ( ; it != repeatedPtrField->pointer_end() ; ++it )
   {
      CommonFields * commonMessage = (CommonFields*) (*it)->GetReflection()->
     MutableMessage ((*it), (*it)->GetDescriptor()->FindFieldByName ("common"));
      if(commonMessage->id() == id)
      {
     return *it;
      }
   }
   return NULL;
}

NOTE : in the example above, the proto message will ALWAYS have a field called common (which in my case is also a proto message). You can replace that by anything that you want to make the comparison from your proto messages.

In the case where I had this class:

class Description : public ::google::protobuf::Message {
  // ...
  inline void add_field(const ::std::string& value);
  inline const ::google::protobuf::RepeatedPtrField< ::std::string>& field() const;
  // ...
};

I used std::find to only add a value if it didn't exist in the list:

#include <algorithm>

void addField(Description& description, const std::string& value) {
    const auto& fields = description.field();
    if (std::find(fields.begin(), fields.end(), value) == fields.end()) {
        description.add_field(value);
    }
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM