如何使用JavaScript切换数组中的元素?

66

以下是我为这个简单任务编写的 javascript 代码:

  1. 如果该元素存在于数组中,则删除它。
  2. 如果该元素不在数组中,则添加它。

if(_.contains(this.types,type_id)){
    var index = this.types.indexOf(type_id);
    this.types.splice(index,1);
}
else{
    this.types.push(type_id);
}

有更有效的方法吗?


你能确定该元素最多只出现一次吗? - GameAlchemist
是的,在数组中一个元素应该只出现一次。 - wwli
8个回答

66

您可以在不使用第三方库的情况下完成此操作,这样会更有效率,像这样。 (如果找到,则仅删除值的第一个实例,而不是多个实例)

Javascript

var a = [0, 1, 2, 3, 4, 6, 7, 8, 9],
    b = 5,
    c = 6;

function addOrRemove(array, value) {
    var index = array.indexOf(value);

    if (index === -1) {
        array.push(value);
    } else {
        array.splice(index, 1);
    }
}

console.log(a);

addOrRemove(a, b);
console.log(a);

addOrRemove(a, c);
console.log(a);

输出

[0, 1, 2, 3, 4, 6, 7, 8, 9]
[0, 1, 2, 3, 4, 6, 7, 8, 9, 5]
[0, 1, 2, 3, 4, 7, 8, 9, 5] 

jsfiddle


1
这个回答是不明智的。第三方库并不比你自己的代码本质上更低效。事实上,它通常使用开发资源更高效,因为你不需要重新发明轮子。此外,在这里展示的代码具有相同的次优渐进复杂度。而6502提供的被接受的答案实际上达到了最优复杂度,更好一些。 - Julian

48

1
你是不是指的是 Array.includes? - SKuijers
@SKuijers .includes 是一个原型数组方法,因此它直接用于数组。 - Rohan Bhangui

46

使用 lodash 的“xor”函数

_.xor([2, 1], [2, 3]);
// => [1, 3]

如果你的第二个参数不是一个数组,你可以简单地将变量包装成一个数组。

var variableToInsertOrRemove = 2;
_.xor([2, 1], [variableToInsertOrRemove]);
// => [1]
_.xor([1, 3], [variableToInsertOrRemove]);
// => [1, 2, 3]

这里是文档:https://lodash.com/docs/4.16.4#xor


太棒了,非常干净的方法!谢谢。 - mmike
2
请注意,这将返回一个新的数组,而不是修改原始数组。 - Julian

21

如果您关心效率,那么使用数组来实现集合可能不是一个好主意。例如,使用对象,您可以执行以下操作:

function toggle(S, x) {
    S[x] = 1 - (S[x]|0);
}

经过多次添加/删除操作后,您可以仅保留值为1的键。

这样,每次添加/删除操作的效率为 O(1),并且您只需要执行一次 O(n) 操作即可得到最终结果。

如果键都是“小”数字,则使用位掩码甚至值得一试(未经测试)

function toggle(S, x) {
    var i = x >> 4;
    S[i] = (S[i]|0) ^ (1<<(x&15));
}

1
+1 表示在可能性为 O(1) 的情况下,只要我们知道 OP 所试图实现的目标即可。 - Xotic750

5

看看这个类似问题的答案

Lodash问题

Lodash代码片段

代码:

function toggle(collection, item) {
  var idx = collection.indexOf(item);
  if (idx !== -1) {
    collection.splice(idx, 1);
  } else {
    collection.push(item);
  }
}

5
这只是将变量重命名后Xotic750的答案的复制。 - Hybrid web dev
这不是Xotic750的答案!请更加仔细地阅读我的回答!这个想法来自@nnnnnn的答案,而不是Xotic750!我在第一个链接(https://dev59.com/EGMl5IYBdhLWcg3wAC-h#18765477)中提到了它! - WebBrother

2
如果“types”可以是一个集合,则:
let toggle = type_id => this.types.delete(type_id) || this.types.add(type_id);

1

使用underscorejs

function toggle(a,b)
{
return _.indexOf(a,b)==-1?_.union(a,[b]):_.without(a,b);
}

使用方法:

var a = [1,2,3];
var b = [4];
a = toggle(a,b); // [1,2,3,4]
a = toggle(a,b); // [1,2,3]

1

扩展Xotic750的答案,这将始终确保在数组中仅出现一次切换元素。如果您的数组有点随机,比如用户输入,可以使用此功能。

function toggleValueInArray(array, value) {
  var index = array.indexOf(value);

  if (index == -1) {
    array.push(value);
  } else {
    do {
      array.splice(index, 1);
      index = array.indexOf(value);
    } while (index != -1);
  }
}


var a = [0, 1, 2, 3, 4, 5, 5, 6, 7, 8, 9],
  b = 5,
  c = 10;

// toString just for good output
console.log(a.toString());

toggleValueInArray(a, b);
console.log(a.toString());

toggleValueInArray(a, c);
console.log(a.toString());


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