Tessil / ordered-map

C++ hash map and hash set which preserve the order of insertion
MIT License
512 stars 66 forks source link

How can I insert into a specific position? #6

Closed Mark-Joy closed 7 years ago

Mark-Joy commented 7 years ago

tsl::ordered_set<int> test{1, 3, 5, 7, 9}; I want to insert number 6 into between 5 and 7. Expected result: {1, 3, 5, 6, 7, 9} The below code always inserts into last position.

tsl::ordered_set<int> test{1, 3, 5, 7, 9};
test.insert(test.begin() + 3, 6);
std::cout << "ordered_set: ";
for (auto & i : test)
{
        std::cout << i << " ";
}
std::cout <<"\n\n";

output: ordered_set: 1 3 5 7 9 6

Tessil commented 7 years ago

It's not possible currently.

The iterator parameter in the insert is a hint similar to the hint parameter in std::unordered_map insert (the library mimics the interface of a map more than a vector).

It would be possible to add a method for that, but it would be quite slow as we have to shift all the values coming after the position in the values_container but also remap all these values in the buckets array.

I have to think a bit if there is a way to add this method while keeping a coherent API.

Tessil commented 7 years ago

I added a insert_at_position method in a test branch.

tsl::ordered_set<int> test{1, 3, 5, 7, 9};
test.insert_at_position(test.begin() + 3, 6);
std::cout << "ordered_set: ";
for (auto & i : test)
{
        std::cout << i << " ";
}
std::cout <<"\n\n";

output: ordered_set: 1 3 5 6 7 9

I have to add some tests and see if there is a better way to do it, but you can already try it.

But note that the method is not fast, it has to shift all the N values on its right (like for vector), but also change the pointers in the buckets array which require the equivalent of N finds.

Mark-Joy commented 7 years ago

Thank you for adding new method. Currently I skip the "insert into a specific position" part and release the code. Whenever I get back to it I will give my comment. I understand that it can be slow, but speed is not an issue in my code. I just need a convenient library to keep the inserted order, and you are doing a great job for creating this library. Now with new method adding, your user will have a complete solution on ordered_map/set matter. If it is possible, I suggest adding one more method which is the "index_of" a key/value. This can easily be done from user side by subtracting iterator but I am not sure if there's a better way.

Tessil commented 7 years ago

Thanks, I added a iterator nth(size_type index) method in the master (and its const equivalent) similar to boost::flat_map.

You could use map.begin()[3] to achieve the same results but it will be effectively more intuitive with a dedicated method.

Tessil commented 7 years ago

Changes from the branch are now in the master. Sorry for the delay, I wanted to do some other changes first.