How to remove list of splices from array in JavaScript?

梦想的初衷 提交于 2021-01-28 05:26:44

问题


I have list of indexes:

var remove_list = [ [ 7, 12 ], [ 12, 14 ] ];

and list of tokens of S-Expression from Scheme lisp.

var tokens = [
  '(',  'let', '(',   '(',
  'x',  '10',  ')',   '#;',
  '(',  'foo', 'bar', ')',
  '#;', 'xxx', ')',   '(',
  '*',  'x',   'x',   ')',
  ')'
];

what is the best way to remove all items from tokens. (it suppose to remove inline commands #;(foo bar) ad #;xxx as specified in R7RS).

I can use this:

for (let remove of remove_list) {
    tokens.splice(...remove);
}

because after first call to splice indexes will change. What is simplest way to remove all specified ranges from array?

And for context I have this function that should remove inline comments, I've splitted calculating the indexes from removing them from array, is this good approach?

function strip_s_comments(tokens) {
    var s_count = 0;
    var s_start = null;
    var remove_list = [];
    for (let i = 0; i < tokens.length; ++i) {
        const token = tokens[i];
        if (token === '#;') {
            if (['(', '['].includes(tokens[i + 1])) {
                s_count = 1;
                s_start = i;
            } else {
                remove_list.push([i, i + 2]);
            }
            i += 1;
            continue;
        }
        if (s_start !== null) {
            if ([')', ']'].includes(token)) {
                s_count--;
            } else if (['(', '['].includes(token)) {
                s_count++;
            }
            if (s_count === 0) {
                remove_list.push([s_start, i + 1]);
                s_start = null;
            }
        }
    }
    for (let remove of remove_list) {
        tokens.splice(...remove);
    }
    return tokens;
}

回答1:


You have two options:

  1. Work in reverse order, or

  2. Keep track of how much you've removed and take that into account with later indexes

Here's an example of #1:

const reverse = remove_list.sort(([a], [b]) => b - a);
for (const [begin, end] of reverse) {
    tokens.splice(begin, end - begin);
}

var remove_list = [ [ 7, 12 ], [ 12, 14 ] ];

var tokens = [
  '(',  'let', '(',   '(',
  'x',  '10',  ')',   '#;',
  '(',  'foo', 'bar', ')',
  '#;', 'xxx', ')',   '(',
  '*',  'x',   'x',   ')',
  ')'
];

const reverse = remove_list.sort(([a], [b]) => b - a);
for (const [begin, end] of reverse) {
    tokens.splice(begin, end - begin);
}

console.log(tokens);

Here's an example of #2:

let removed = 0;
for (const [begin, end] of remove_list) {
    removed += tokens.splice(begin - removed, end - begin).length;
}

var remove_list = [ [ 7, 12 ], [ 12, 14 ] ];

var tokens = [
  '(',  'let', '(',   '(',
  'x',  '10',  ')',   '#;',
  '(',  'foo', 'bar', ')',
  '#;', 'xxx', ')',   '(',
  '*',  'x',   'x',   ')',
  ')'
];

let removed = 0;
for (const [begin, end] of remove_list) {
    removed += tokens.splice(begin - removed, end - begin).length;
}

console.log(tokens);



回答2:


Traverse from end to start of list and use copyWithin.

function remove(dat, list) {
  const arr = [...dat];
  const is_remove = index =>
    list.some(([start, end]) => index >= start && index <= end);

  for (let i = arr.length - 1; i > -1; i--) {
    if (is_remove(i)) {
      arr.copyWithin(i, i + 1).pop();
    }
  }
  return arr;
}

function remove2(dat, list) {
  const arr = [...dat];
  let new_len = arr.length;
  for (let i = list.length - 1; i > -1; i--) {
    const [start, end] = list[i];
    arr.copyWithin(start, end + 1);
    new_len -= end - start + 1;
  }
  arr.length = new_len;
  return arr;
}

// Alternate way
const remove3 = (arr, list) =>
  arr.filter((_, i) => !list.some((rg) => i >= rg[0] && i <= rg[1]));


var remove_list = [ [ 7, 11 ], [ 12, 14 ] ];
var tokens = [
  '(',  'let', '(',   '(',
  'x',  '10',  ')',   '#;',
  '(',  'foo', 'bar', ')',
  '#;', 'xxx', ')',   '(',
  '*',  'x',   'x',   ')',
  ')'
];

console.log(remove(tokens,remove_list).join(''));
console.log(remove2(tokens,remove_list).join(''));
console.log(remove3(tokens,remove_list).join(''));


来源:https://stackoverflow.com/questions/62278398/how-to-remove-list-of-splices-from-array-in-javascript

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!