如何从 JavaScript 中的数组中删除拼接列表?
How to remove list of splices from array in JavaScript?
我有索引列表:
var remove_list = [ [ 7, 12 ], [ 12, 14 ] ];
以及来自 Scheme lisp 的 S-Expression 的标记列表。
var tokens = [
'(', 'let', '(', '(',
'x', '10', ')', '#;',
'(', 'foo', 'bar', ')',
'#;', 'xxx', ')', '(',
'*', 'x', 'x', ')',
')'
];
从令牌中删除所有项目的最佳方法是什么。 (它假设删除 R7RS 中指定的内联命令 #;(foo bar)
和 #;xxx
)。
我可以用这个:
for (let remove of remove_list) {
tokens.splice(...remove);
}
因为第一次调用拼接索引后会发生变化。从数组中删除所有指定范围的最简单方法是什么?
对于上下文,我有这个函数应该删除内联注释,我将计算索引与从数组中删除它们分开了,这是好方法吗?
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 的示例:
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);
这是#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);
从列表的末尾遍历到列表的开头并使用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(''));
我有索引列表:
var remove_list = [ [ 7, 12 ], [ 12, 14 ] ];
以及来自 Scheme lisp 的 S-Expression 的标记列表。
var tokens = [
'(', 'let', '(', '(',
'x', '10', ')', '#;',
'(', 'foo', 'bar', ')',
'#;', 'xxx', ')', '(',
'*', 'x', 'x', ')',
')'
];
从令牌中删除所有项目的最佳方法是什么。 (它假设删除 R7RS 中指定的内联命令 #;(foo bar)
和 #;xxx
)。
我可以用这个:
for (let remove of remove_list) {
tokens.splice(...remove);
}
因为第一次调用拼接索引后会发生变化。从数组中删除所有指定范围的最简单方法是什么?
对于上下文,我有这个函数应该删除内联注释,我将计算索引与从数组中删除它们分开了,这是好方法吗?
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 的示例:
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);
这是#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);
从列表的末尾遍历到列表的开头并使用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(''));