标题可能没有多大意义,但你会怎样做:
a = [1, 2, 2, 3, 3, 3];
b = [1, 2, 3];
a.subtract(b);
我希望这返回[2,3,3],而不是[]就像其他类似问题的答案一样,只保留不在其他数组中的项目,而不是只删除多少在另一个阵列中。
答案 0 :(得分:1)
您可以为Array
创建原型,并通过检查并删除找到的元素来过滤数组。
Array.prototype.subtract = function (array) {
array = array.slice();
return this.filter(function (a) {
var p = array.indexOf(a);
if (p === -1) {
return true;
}
array.splice(p, 1);
});
}
var a = [1, 2, 2, 3, 3, 3],
b = [1, 2, 3];
console.log(a.subtract(b));

带有哈希表的更快版本:
Array.prototype.subtract = function (array) {
var hash = Object.create(null);
array.forEach(function (a) {
hash[a] = (hash[a] || 0) + 1;
});
return this.filter(function (a) {
return !hash[a] || (hash[a]--, false);
});
}
var a = [1, 2, 2, 3, 3, 3],
b = [1, 2, 3];
console.log(a.subtract(b));

答案 1 :(得分:1)
您可以使用filter()
和indexOf()
检查其他数组中是否存在元素,是否使用splice()
var a = [1, 2, 2, 3, 3, 3];
var b = [1, 2, 3];
var result = a.filter(function(e) {
let i = b.indexOf(e)
return i == -1 ? true : (b.splice(i, 1), false)
})
console.log(result)

答案 2 :(得分:0)
这是一种可以执行此操作的方法:遍历数组b
并检查它是否存在于数组a
中。如果是,请在其索引处插入undefined
。返回已过滤的a
数组以删除所有undefined
元素。
编辑:实际上不需要过滤器使用splice()
其他人使用过。
let a = [1, 2, 2, 3, 3, 3];
let b = [1, 2, 3];
let sub = function(a, b) {
for (i in b) {
let index = a.indexOf(b[i]);
if (index != -1) {
a.splice([index],1)
}
}
return a
}
console.log(sub(a, b))
答案 3 :(得分:0)
这里建议使用indexOf()
检查存在的答案是低效的O(n ^ 2)运行时。更有效的方法是使用Map
并使用has()
检查是否存在,将运行时间降低到O(n):
// see the bottom of the answer for a more efficient implementation than this
Object.defineProperty(Array.prototype, 'subtract', {
configurable: true,
value: function subtract (array) {
return this.filter(
function (element) {
const count = this.get(element)
if (count > 0) {
this.set(element, count - 1)
}
return count === 0
}, array.reduce(
(map, element) => {
if (map.has(element)) {
map.set(element, map.get(element) + 1)
} else {
map.set(element, 1)
}
return map
}, new Map()
)
)
},
writable: true
})
let a = [1, 2, 2, 3, 3, 3]
let b = [1, 2, 3]
console.log(a.subtract(b))

这是一个测试平台,用于显示此解决方案的效率与@Nina的答案相比:
Array.prototype.ninaSubtract = function (array) {
var hash = Object.create(null);
array.forEach(function (a) {
hash[a] = (hash[a] || 0) + 1;
});
return this.filter(function (a) {
return !hash[a] || (hash[a]--, false);
});
}
Object.defineProperty(Array.prototype, 'patrickSubtract', {
configurable: true,
value: function subtract (array) {
return this.filter(
function (element) {
const count = this.get(element)
if (count > 0) {
this.set(element, count - 1)
}
return count === 0
}, array.reduce(
(map, element) => {
if (map.has(element)) {
map.set(element, map.get(element) + 1)
} else {
map.set(element, 1)
}
return map
}, new Map()
)
)
},
writable: true
})
let a = [1, 2, 2, 3, 3, 3]
let b = [1, 2, 3]
let ninaStart = 0
let ninaStop = 0
let patrickStart = 0
let patrickStop = 0
ninaStart = performance.now()
for (let i = 100000; i > 0; i--) {
a.ninaSubtract(b)
}
ninaStop = performance.now()
patrickStart = performance.now()
for (let i = 100000; i > 0; i--) {
a.patrickSubtract(b)
}
patrickStop = performance.now()
console.log('Nina time: ', ninaStop - ninaStart, 'ms')
console.log('Patrick time: ', patrickStop - patrickStart, 'ms')

使用Chrome v60在我的笔记本电脑上运行多次表示Nina使用普通对象更新的答案比我的答案快约13%。
让我们通过改进她的回答来试图击败它:
Array.prototype.ninaSubtract = function (array) {
var hash = Object.create(null);
array.forEach(function (a) {
hash[a] = (hash[a] || 0) + 1;
});
return this.filter(function (a) {
return !hash[a] || (hash[a]--, false);
});
}
Object.defineProperty(Array.prototype, 'patrickSubtract', {
configurable: true,
value: function subtract (array) {
const lookup = Object.create(null)
const output = []
for (let index = 0; index < array.length; index++) {
const element = array[index]
lookup[element] = element in lookup ? lookup[element] + 1 : 1
}
for (let index = 0; index < this.length; index++) {
const element = this[index]
if (!(element in lookup) || lookup[element]-- <= 0) {
output.push(element)
}
}
return output
},
writable: true
})
let a = [1, 2, 2, 3, 3, 3]
let b = [1, 2, 3]
let ninaStart = 0
let ninaStop = 0
let patrickStart = 0
let patrickStop = 0
ninaStart = performance.now()
for (let i = 100000; i > 0; i--) {
a.ninaSubtract(b)
}
ninaStop = performance.now()
patrickStart = performance.now()
for (let i = 100000; i > 0; i--) {
a.patrickSubtract(b)
}
patrickStop = performance.now()
console.log('Nina time: ', ninaStop - ninaStart, 'ms')
console.log('Patrick time: ', patrickStop - patrickStart, 'ms')
&#13;
由于它避免使用reduce()
,forEach()
或filter()
以减少函数调用的上下文切换,因此性能更高,但规范性更低。这个解决方案几乎是Nina更新答案的一半时间(大约快43%):
Object.defineProperty(Array.prototype, 'subtract', {
configurable: true,
value: function subtract (array) {
const lookup = Object.create(null)
const output = []
for (let index = 0; index < array.length; index++) {
const element = array[index]
lookup[element] = element in lookup ? lookup[element] + 1 : 1
}
for (let index = 0; index < this.length; index++) {
const element = this[index]
if (!(element in lookup) || lookup[element]-- <= 0) {
output.push(element)
}
}
return output
},
writable: true
})
let a = [1, 2, 2, 3, 3, 3]
let b = [1, 2, 3]
console.log(a.subtract(b))
&#13;
之前性能差异的原因是因为我之前使用Set
的算法不正确。如果b
包含非唯一元素,则输出将不正确。