Deleting multiple array elements by indexes

Hello Yjs community,

The following code will sometimes result in × Unhandled Rejection (Error): Length exceeded!, depending on how many and where deletions are happening.

const elementArray: Y.Array<Y.Map<any>> = doc.getArray("myarray");

doc.transact(() => {
  elementArray.forEach((element: Y.Map<any>, index: number) => {
    if (...) { // Some arbitrary condition.
      elementArray.delete(index);
    }
  });
});

I stepped through the code and noticed the delete() call immediately removes the element and reduces the array length by 1, unsurprisingly. Meaning deleting an element at index is impossible when length - deleted < index. So my solution is to add a counter like this:

const elementArray: Y.Array<Y.Map<any>> = doc.getArray("myarray");

doc.transact(() => {

  let deletedCount = 0;

  elementArray.forEach((element: Y.Map<any>, index: number) => {
    if (...) { // Some arbitrary condition.
      elementArray.delete(index - deletedCount);
      deletedCount++;
    }
  });
});

This works but feels problematic for reasons unknown. I haven’t tested this in a real-world collaboration environment either. So my question is: is there a proper way to delete multiple elements from an array with non-sequential indexes? Am I missing something?

Thank you!

Joe

Having a quick look at the code it seems right. Though you’ve got an if statement there rather than doing it by index. So couple of ideas:

  1. If you have a list on indices to remove then you can just forEach that list of indices in reverse order and delete from right to left.

  2. contribute a filter function to Y.array (looks fairly easy to do)

2 Likes

Awesome. thanks for the suggestions