-1

I have a set of a class Item :

std::set <Item> items; 

class Item
{
   private:
      std::string name;
      std::string serialNum; 
      int count; 
      double unitPrice;
  public :
      Item(std::string _name, std::string _serialNum, int _count, double _unitPrice); 
      Item(); // Ctor with no parameters , for compiling 
      ~Item(); //Dtor 
      double totalPrice();
      bool operator<(Item const & other)const;
      bool operator>(Item& other);
      bool operator==(Item& other);
      void operator=(const Item& other);
      void countUp();
      void countDown();
      void setup(std::string _name, std::string _serialNum, int _count, double _UnitPrice); 
      int getCount() const ;
      std::string getName() const;
      std::string  getSerial() const ;
      double getPrice() const ;
      void printItem() const ;
 };

can I search in the set only by one value ? for instance, search in the set by item :: name .

Noam
  • 96
  • 1
  • 12

2 Answers2

2

std::set is ordered (in general using operator< which you can overload for your type). Usually, you decide for one specific order. (Maybe it is the serialNum in your case?)

If you are searching the same set with a different criterion, e.g. name in your case, you need to traverse the whole set element by element, since there is no profit in the set order.

For this, there is the standard algorithm std::find_if, which does this in linear time:

std::string name_to_find = "foo bar";

auto it = std::find_if(items.begin(), items.end(),
             [name_to_find](const Item & i){ return i.getName() == name_to_find; });

will give you an iterator it pointing to the first item in the set which has the name name_to_find (the end-iterator if no such element exists in the set). It is independent of the container type you supply, so it works with set, vector, arrays, ..., and ignores possible order of the container.


The above code uses C++11 lambda to provide a compare function literally inline. If your compiler doesn't support that yet (or if you want to support older compilers), you have to use a functor to provide the same functionality. A functor is a class which acts like a function (can be called using operator()).

// Functor class to compare the name of an item with a specific name to look for
struct ItemByName {
    // The functor needs to remember what we're looking for in a member variable
    std::string name_to_find;

    // Constructor initializing the name to look for
    ItemByName(std::string name_to_find) : name_to_find(name_to_find) {}

    // The call-operator which is called by the algorithm find_if
    bool operator()(const Item &i) const {
        // This is the same body as in the lambda
        return i.getName() == name_to_find;
    }
};

and then use this in find_if by constructing an instance of this functor:

std::set<Item>::iterator it = std::find_if(items.begin(), items.end(),
             ItemByName(name_to_find));

Note that the returned value is now captured in a variable with explicit type. In C++11 (above), we can use auto to make this easier to type.

leemes
  • 44,967
  • 21
  • 135
  • 183
  • thnak you , this is what I looked for . can std :: finf_if be used in c++ 98 ? – Noam Jan 08 '15 at 11:29
  • Yes it should be available there. But the compare function can not be written inline (as a lambda) but outside as a functor. I'll update the answer to show a C++98 compatible code. – leemes Jan 08 '15 at 11:30
  • ok thank you , I don't understand what you meant by inline " (as a lambada) " , I hope it is not too important for understanding your answer . – Noam Jan 08 '15 at 11:32
  • Now I updated the answer. As you can see, now the implementation for "how to compare an item with the name" is written in an additional class. In the previous code, this was written exactly when calling `find_if` (that's what I meant with "inline": you define it where you use it) – leemes Jan 08 '15 at 11:36
0

Set description. Set find, Set key comp. When you create a set you can provide Compare class that will be used to compare elements. According to spec:

A binary predicate that takes two arguments of the same type as the elements and returns a bool. The expression comp(a,b), where comp is an object of this type and a and b are key values, shall return true if a is considered to go before b in the strict weak ordering the function defines. (...) defaults to less, which returns the same as applying the less-than operator (a

By default set uses less<T> to compare elements, but you can provide a class that compare items in a manner defined by you.

kkamil
  • 2,593
  • 11
  • 21
  • but I only want to compare buy the itme name , the other fields are not important , and set key compare 0 compares all of the item fields – Noam Jan 08 '15 at 11:20
  • As I understood the question, it is about searching by **any** member **after** the set was declared. You can only specify **one specific** order for the set variable. – leemes Jan 08 '15 at 11:39