For completeness’ sake, a p5js flavor version as well:
/**
* indicesOf() & splitListAsList2d() (v1.0.4)
* GoToLoop (2020/Feb/25)
*
* https://Discourse.Processing.org/t/
* splitting-an-arraylist-for-each-pvector-0-0-updated/17883/16
*
* https://www.OpenProcessing.org/sketch/847230
*/
'use strict';
const vecs = [];
let vecs2d, delimVec, extraDelimVec;
function setup() {
noCanvas();
delimVec = createVector();
extraDelimVec = new p5.Vector(Math.E, TAU, PI);
vecs.push(createVector()); // 0
vecs.push(delimVec); // 1
vecs.push(createVector(100, 100)); // 2
vecs.push(new p5.Vector(150, 100)); // 3
vecs.push(createVector(150, 150)); // 4
vecs.push(extraDelimVec); // 5
vecs.push(createVector(300, 100)); // 6
vecs.push(null); // 7
vecs.push(extraDelimVec); // 8
vecs.push(delimVec); // 9
vecs.push(createVector(350, 100)); // 10
vecs.push(createVector(350, 150)); // 11
vecs.push(extraDelimVec); // 12
vecs.push(delimVec); // 13
print(vecs);
const delimIndexes = indicesOf(vecs, // list[]
p5.Vector.prototype.equals, // equals()
delimVec, extraDelimVec); // ...delims[]
print(delimIndexes);
vecs2d = splitListAsList2d(vecs, delimIndexes);
for (const vecs1d of vecs2d) print(vecs1d);
for (const vecs1d of vecs2d) console.table(vecs1d);
print(vecs2d.length);
}
function indicesOf(list, equals, ...delims) {
if (!(list && _len(list) && _isIterable(list))) {
console.warn("Parameter 'list' is empty or non-iterable container!");
return new Uint32Array;
}
if (delims.length == 1 && _isIterable(delims[0])) delims = delims[0];
const indices = [],
gotDelims = !!_len(delims),
useEquals = typeof equals == 'function';
var i = 0;
for (const elem of list.values()) {
if (!elem) indices.push(i);
else if (gotDelims) for (const delim of delims.values())
if (useEquals? equals.call(elem, delim) : elem == delim) {
indices.push(i);
break;
}
++i;
}
return new Uint32Array(indices);
}
function splitListAsList2d(list, ...indices) {
const list2d = [], size = _len(list), lastIdx = size - 1;
if (!(list && size && _isIterable(list))) {
console.warn("Parameter 'list' is empty or non-iterable container!");
return list2d;
}
const indexes = _validateIndices(lastIdx, ...indices);
if (!indexes.length) return list2d;
if (_isHashable(list)) list = [...list.values()];
for (let list1d, sequenceGotInterrupted = true, i = 0; i < size; ++i) {
if (indexes.includes(i)) {
sequenceGotInterrupted = true;
continue;
}
if (sequenceGotInterrupted) {
list2d.push(list1d = []);
sequenceGotInterrupted = false;
}
list1d.push(list[i]);
}
return list2d;
}
function _validateIndices(maxIndex, ...indices) {
if (indices.length == 1 && _isIterable(indices[0])) indices = indices[0];
if (!_len(indices)) {
console.warn("Parameter 'indices' is an empty container!");
return new Uint32Array;
}
const maxIdx = min(abs(maxIndex), 2**32 - 1), indexes = new Set;
for (const idx of indices.values())
idx >= 0 && idx <= maxIdx && indexes.add(parseInt(idx));
return new Uint32Array(indexes).sort();
}
function _len(obj) {
return abs(parseInt(obj && ('size' in obj? obj.size : obj.length))) || 0;
}
function _isIterable(obj) {
return obj && typeof obj.values == 'function';
}
function _isHashable(obj) {
return obj && typeof obj.has == 'function';
}