JSFiddle - React, Tailwind, and code Playground
Proxy: python-like array slicing
by Csaba Hellinger
JavaScript
function pythonIndex(array) {
function parse(value, defaultValue, resolveNegative) {
if (value === undefined || isNaN(value)) {
value = defaultValue;
} else if (resolveNegative && value < 0) {
value += array.length;
}
return value;
}
const handler = {
get (arr, prop) {
if (typeof prop === 'string' && prop.match(/^[+-\d:]+$/)) {
// no ':', return a single item
if (prop.indexOf(':') === -1) {
let index = parse(parseInt(prop, 10), 0, true);
console.log(prop, /*'PARTS', index, ' - SINGLE RESULT',*/ ' ', array[index]);
return array[index];
}
// otherwise: parse the slice string
let [start, end, step] = prop.split(':').map(part => parseInt(part, 10));
step = parse(step, 1, false);
if (step === 0) {
throw new RangeError('Step can\'t be zero');
}
if (step > 0) {
start = parse(start, 0, true);
end = parse(end, array.length, true);
} else {
start = parse(start, array.length - 1, true);
end = parse(end, -1, true);
}
let result = [];
for (let i = start; start <= end ? i < end : i > end; i += step) {
result.push(array[i]);
if (i < 0 || i > 10) { throw new Error('ABORT'); } // TODO: remove
}
console.log(prop, /*' - PARTS', start, end, step, ' - RESULT',*/ ' ', result);
return result;
}
return Reflect.get(array, prop);
}
};
return new Proxy(array, handler);
}
console.clear();
let myArr = pythonIndex([0,1,2,3,4,5,6,7,8,9])
myArr['-1']; // 9
myArr['0:3']; // [0,1,2]
myArr['8:5:-1']; //...