swannodette / mori

ClojureScript's persistent data structures and supporting API from the comfort of vanilla JavaScript
http://swannodette.github.io/mori
3.39k stars 148 forks source link

Removing items positionally from a vector #34

Closed mlanza closed 10 years ago

mlanza commented 11 years ago

First off, thanks for creating Mori. I am making use of it in a long-term project and it appears to be a good fit for my needs.

I am wondering if it would be possible to port the JavaScript splice method into Mori. It would effectively allow removal and/or insert into sequences where item order is pertinent. Currently, conj seems limiting as it allows no flexibility as to where an item is added. Maybe subvec could play a part in this?

When you consider for example that sometimes order is a significant thing in the real world, it makes sense to allow for the ordering of data even in persistent data structures. For example, a user creates a vector of todos, adding one after the other and then occasionally prioritizes them, moving the more important ones up the list.

Currently, when I manipulate the order, it requires that I first call into_array, perform the reordering, and then reconstitute the vector. I am hoping that existing internal data structures can be reused in allowing for the same operation with greater efficiency.

In another use case, it is possible that a todo is completed and thus removed from the list from somewhere in the middle. I realize there is a remove method that could be used but I wonder about efficiency. When your GUI is already aware of the index of a given item, it seems that this fact would allow for a more efficient operation. For example when you remove an item from a list of hundreds of items and you already know the index that must be better than having to filter it out via remove. It would also probably be useful if one could retrieve the position of an item in a sequence (i.e. indexOf) as this would go hand in hand with splice and even nth. At the very least, providing splice would provide a familiar and immensely useful api.

Obviously, I could add these methods myself, but I think I'd end up with something that internally was as inefficient as the workarounds I'm already utilizing.

swannodette commented 11 years ago

I'll think on it, thanks for the feedback.

swannodette commented 11 years ago

I think splice doesn't really make sense since it really cannot be done efficiently for vectors. However good progress has been made to Clojure RRB-Vectors which do support this. I'll likely be including this in the future.

I'll look into indexOf

mlanza commented 11 years ago

Thank you, Sir. The lack of this is certainly not a deal breaker.

mlanza commented 10 years ago

I am wondering about something related to vectors and if all the crud operations are implemented in a manner that allows for efficient structure reuse. I can see how to create and read the vector; that's straightforward. I can update items at a particular position with assoc, but how would would one remove an item at an arbitrary position?

var v = mori.vector(1, 2, 3, 4, 5);
var v2 = //do what here?
mori.into_array(v2) //=> [1,2,4,5]

The only thing I found is:

mori.into_array(mori.concat(mori.subvec(v, 0, 2), mori.subvec(v, 3, 5)))

But I would have expected:

mori.into_array(mori.concat(mori.subvec(v, 0, 1), mori.subvec(v, 3, 4)))

Or better yet:

mori.dissoc(v, 2) //but this doesn't work for vectors

All I am really after is the most efficient means of removing a portion of a vector while still reusing as much of the original structure as possible. It would seem a waste to have to reconstruct an entire vector, esp. a large one, just to remove a single item. Without this feature the crud operations are incomplete.

swannodette commented 10 years ago

This sort of thing can be done properly with RRB-Trees.

mlanza commented 10 years ago

OK. So then not in Mori's scope.