Moving elements in lists

Makes sense and thanks for the reply! We’ll give it a go in our proof of concept and see how it plays out.

What do you mean by this? Do you mean you should not use a top-level Y.Map?

This is not what I said. Read the answer again. Duane stored millions of GUIDs on the top level structure. Keys on maps can’t be garbage collected (they will be stored in memory even if they have been deleted - to resolve potential sync conflicts). In Duane’s case he was able to organize data in a YArray instead.

Sorry if I misunderstood. I’m just trying to understand what you meant by not using “a top-level data structure.” I was inferring from your previous comment:

I suggest not to use maps as the top-level data structure. Deleted properties will always take up space (the key-name can’t be removed). When you store the data in a Y.Array, you can delete data very efficiently.

The reason I’m asking is because I’m in the midst of designing my data model for an app I’m making and wanted to start off on the right foot.

Sure, no harm in asking. This has nothing to do with Y.Map being used as a top level data structure. This is an inherent problem of the Y.Map type.

Just in his case it was a top-level type. I suggested to use Y.Array instead :wink:

Hi, I just switched from Automerge, what I am wondering is that Automerge does not have special type for Array, so user can use JS Array.splice to split new array from an old one. which help the ‘split_node’ case e.g. for Slate. But with YJS, it seems elements in a Y.Array can not be reused in the other Y.Array, so we can not move a range of elements of Y.Array to the other Y.Array. According to above discuss, move is complex, then how did Automerge did that?

Regarding Array.splice: I don’t think that this is implemented as a move operation in Automerge. Technically, you are simply copying a part of the array and put it somewhere else.

The first post in this thread links to the sources on Automerge’s move implementation. I also highlighted some of the disadvantages of their implementation. If I would implement a move operation in Yjs, I would also like to support moving ranges of content.

Yes, with some workaround we can copy part of the array, BUT, we can not remove the items copied from the old array without it been marked as ‘deleted’, currently, imo.

What were you thinking for and API and can you explain briefly how you’d imagined single/range moves would be implemented?

I would add starting- and ending-markers that point to a different location in the document. We could reuse the marker approach from the rich-text formatting.

Then you could have an API like yarray2.insert(0, [yarray.range(start, end)]) to copy a range of characters from one array to another at a different position. First, I’d implement a new API for selections & ranges that allows you to refer to ranges of content, which is where yarray.range(start, end) comes from. However, I don’t think that moving of elements will be supported this year. There is so much other work to do that is more important. This, however, is an interesting problem that I’d like to solve eventually.

The best approach is to copy the type before you insert it somewhere else. You might duplicate content if two users move an element at the same time. If that is unacceptable, you can implement one of the move approaches we discussed above.

Hey @dmonad, this doesn’t seem that hard to do. I think I could help with a PR that adds this functionality to YXmlElement.

However, it would be necessary to:

  1. Iterate all the descendants of the YXmlElement and clone them.
  2. Iterate all nodes and look for duplicates on each change (ref).

That would be terrible as far as performance goes. Do you think there is a better way?