Splitting an ArrayList for each PVector (0,0) (updated)

For completeness’ sake, a p5js flavor version as well: :smile_cat:

/**
 * 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';
}
2 Likes