使用展开运算符从数组中删除元素

4

我有一个动物数组 arr = ['cat','dog','elephant','lion','tiger','mouse']

我想写一个函数remove(['dog','lion']),它可以从arr中删除元素,我们能否使用es6展开运算符编写此函数?

示例:

arr = ['cat','dog','elephant','lion','tiger','mouse']
remove(['cat', 'lion'])

arr应该被修改为

arr = ['dog','elephant','tiger','mouse']

注意:我不希望进行改变,因此请不要提出会改变数组的解决方案。

请添加一个例子,说明你的意思... - Nina Scholz
4
筛选器不会更改原数组,它会返回一个新的数组。 - Nina Scholz
这个问题及其最初的要求就像是要求用锯子钉锤子一样荒诞无稽。 - Samuli Hakoniemi
function remove(x, y) { return x.length == 0 ? x : y.includes(x[0]) ? remove(x.slice(1), y) : [x[0], ...remove(x.slice(1), y)]; } - Bergi
8个回答

4
不行,因为它们不相邻。有人讨论了进一步采用展开和剩余语法的可能性,但即使在这些讨论中,我认为一系列不连续的选择也不可能实现。我认为最接近的方法是先具体指定前几个,然后对“lion”之后的所有内容使用剩余语法。

const arr = ['cat','dog','elephant','lion','tiger','mouse'];
const arr2 = [arr[1], arr[2], ...arr.slice(4)];
console.log(arr2);

我相信这不是你想做的事情。:-)


(此文段为英语,意思为“我相信这不是你想做的事情。:-)”)

(抱歉,如果你看到上面的“'cat'”而不是“'dog'”,请刷新。我记错了。) - T.J. Crowder
2
是的,这不是我想要的。但知道这不能做令人难过。 - ThinkGeek

3

From what I understand you're looking for a function that has its argument defined using the spread syntax. Here is an example:

var arr = ['cat','dog','elephant','lion','tiger','mouse'];

function remove(...toRemove){
   toRemove.forEach(item => {
      var index = arr.indexOf(item);
      if(index != -1){
          arr.splice(index, 1);
      }
   })
}

remove('dog', 'lion'); // OR remove(...['dog', 'lion']);
console.log(arr);

实际上,这会改变原始数组(它会使其发生变异)。您提到您不希望进行变异,但您也提到了这个 arr 应该被更改为...


3

我不理解为什么选定的答案被选中,因为它没有提供从数组中删除元素的最终解决方案。

你不能仅使用展开运算符来进行删除操作,但是你可以使用切片和展开运算符:

function removeOne(sourceList, value) {
  const index = sourceList.indexOf(value);
  if (index >= 0 && index < sourceList.length) {
    return [
       ...sourceList.slice(0, index),
       ...sourceList.slice(index+1),
    ];
  }
  return sourceList;
}

function remove(sourceList, removeList) {
  let res = [...sourceList]
  removeList.forEach((item) => {
    res = removeOne(res, item);
  })
  return res;
}


所选答案解释了为什么提问者想要做的事情不可能发生。 - Meredith
@Meredith 哈哈,真的吗?我们是工程师,我们修复损坏的东西,即使问题本身就有问题。此外,我一直认为仅指出问题而不提供/自愿提供信息的答案是毫无帮助的。优秀工程师和糟糕工程师之间的关键区别在于,优秀工程师应始终自愿提供信息并填补知识差距,如果问题/问题没有正确的背景。最后,标题反映了提问者的意图:“使用展开从数组中删除元素”。仅仅说“不”并不能满足问题的意图。 - dhwang

2
您可以使用数组的filter方法,它将返回筛选后的值数组。
var filterMe = ["cat", "dog", "elephant", "lion", "tiger", "mouse"];
var answer = filterMe.filter((item) => item !== "dog")
                     .filter((item) => item !== "lion");
console.log(answer);

item !== "dog" && item !== "lion" - zgr024

1
如果你想传递许多字符串,比如 remove('lion', 'dog'),你可以使用 spread。否则我认为 spread 无法帮助你。

1
你可以使用展开运算符从iterator中排除值进行迭代。
顺便说一句,这并不是一个明智的选择。

function remove(array, items) {
    array[Symbol.iterator] = function* () {
        for (let value of Object.values(this)) {
            if (!items.includes(value)) {
                yield value;
            }
        }
    };
}

var array = ['cat', 'dog', 'elephant', 'lion', 'tiger', 'mouse'];

remove(array, ['dog', 'lion']);
console.log([...array]);
console.log(array);
.as-console-wrapper { max-height: 100% !important; top: 0; }


0
如果您正在使用TypeScript,您还可以使用{{link1:Omit实用程序类型}}从对象/数组中删除特定键。

假设有这样一个接口

interface Todo {
  title: string;
  description: string; // <--- assuming you want to omit `description` key
  completed: boolean;
  createdAt: number;
}
 
type TodoPreview = Omit<Todo, "description">;

TodoPreview类型现在将期望一个对象,其中包括其他成员,但是decription被省略了。

现在将是正确的

const todo: TodoPreview = {
  title: "Clean room",
  completed: false,
  createdAt: 1615544252770,
};

这会导致错误

const todo: TodoPreview = {
  title: "Clean room",
  completed: false,
  description: 'this should not be here' // <--- TS compiler will complain
  createdAt: 1615544252770,
};

这并没有回答问题。一旦您拥有足够的声望,您将能够评论任何帖子;相反,提供不需要询问者澄清的答案。- 来自审核 - mcky

0
与之前的筛选解决方案类似,但使用正则表达式。如果要删除的数组很大,则很有用...

let arr = ['cat', 'dog', 'elephant', 'lion', 'tiger', 'mouse'];
const removeArr = ['cat', 'lion'];
const removeRegExp = new RegExp(removeArr.join('|'));
arr = arr.filter(e => !removeRegExp.test(e));
console.log(arr);


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接