3

Which is the best container in C++ which can -

  • store only unique values (such as set)
  • can lookup those values using index in constant time (such as array)

I basically need to to iterate in phase one and collect all the unique elements, order really doesn't matter.

However, in phase two, I then have to provide each element in the container, but can only provide it one by one. Since caller can know the size of my container, it provides me index one by one, such that 0 < idx < size of the container.

Right now, the only solution that comes to my mind is two maintain two containers vector and set, I am wondering is there any container that provides the same?

class MyContainer{
  private:
   std::set<Fruits> setFruits;
   std::vector<Fruits> arrFruits; // can have indexed access

  public:
    void collectFruits(const Fruits& fruit){
       if(setFruits.find(fruit) == setFruits.end()){ 
       // insert only if it doens't contains
          setFruits.insert(fruit);
          arrFruits.push_back(fruit);
       }
     }
 };
10
  • set also orders the values. Do you need them to be ordered, or merely that there be no duplicates? Commented Aug 4, 2015 at 23:33
  • no duplicates! order is not important! Commented Aug 4, 2015 at 23:35
  • unordered set has "Search, insertion, and removal have average constant-time complexity" which means O(1) on average. Commented Aug 4, 2015 at 23:35
  • 2
    You could use a vector, but with an custom insert function that checks for duplicates on insert Commented Aug 4, 2015 at 23:38
  • 2
    Can you explain a bit about why you want to look up the values with an index? Since you don't require them to have stable order I'm struggling to see what benefit there is to look them up by index. Commented Aug 4, 2015 at 23:39

2 Answers 2

4

Alex Stepanov, the creator of STL, once said "Use vectors whenever you can. If you cannot use vectors, redesign your solution so that you can use vectors." With that good advice in mind:

Phase 1: Collect the unique elements

std::vector<Foo> elements;

// add N elements
elements.push_back(foo1);
...
elements.push_back(fooN);

// done collecting: remove dupes
std::sort(elements.begin(), elements.end());
elements.erase(std::unique(elements.begin(), elements.end()),
               elements.end());

Phase 2: Well, now we have a vector of our k unique elements, with constant-time index access (with indices 0..k-1).

Sign up to request clarification or add additional context in comments.

3 Comments

This can be expensive if there are lots of duplicates, though.
Thanks, Barry! But in that case I can even use set during collection and convert to vector to have constant-time index access..
@T.C. Absolutely. I'm just going on the [likely completely unfounded] assumption that phase 2 is the important one :)
2

You could use a boost flat_set.

I don't think it provides an operator[] but it has random access iterators and has a constant time nth() function that returns an iterator with a particular index.

Inserting may invalidate iterators but providing you do all insertions in phase 1 and then all index access in phase 2 you should be ok.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.