我有两个数组。第一个数组包含一些值,而第二个数组包含应从第一个数组中删除的值的索引。例如:
var valuesArr = new Array("v1","v2","v3","v4","v5");
var removeValFromIndex = new Array(0,2,4);
我想从0,2,4
中移除索引valuesArr
中的值。我认为原生的splice
方法可能会有所帮助,所以我想出了:
$.each(removeValFromIndex,function(index,value){
valuesArr.splice(value,1);
});
但它不起作用,因为在每个splice
之后,valuesArr
中的值的索引是不同的。我可以通过使用临时数组并将所有值复制到第二个数组来解决这个问题,但我想知道是否有任何本机方法可以传递多个索引来从数组中删除值。
我更喜欢jQuery解决方案。 (不确定我是否可以在这里使用grep
)
答案 0 :(得分:204)
总是存在普通的旧for
循环:
var valuesArr = ["v1","v2","v3","v4","v5"],
removeValFromIndex = [0,2,4];
for (var i = removeValFromIndex.length -1; i >= 0; i--)
valuesArr.splice(removeValFromIndex[i],1);
以相反的顺序浏览removeValFromIndex
,您可以.splice()
而不会弄乱尚未删除的项目的索引。
请注意,在上面我使用了带有方括号的array-literal语法来声明这两个数组。这是推荐的语法,因为new Array()
使用可能会造成混淆,因为它会根据您传入的参数数量做出不同的响应。
编辑:刚刚看到你对另一个关于索引数组的答案的评论不一定是任何特定的顺序。如果是这种情况,只需在开始之前将其按降序排序:
removeValFromIndex.sort(function(a,b){ return b - a; });
然后按照您喜欢的循环/ $.each()
/等方法进行操作。
答案 1 :(得分:18)
答案 2 :(得分:18)
这是我在不使用lodash / underscore时使用的一个:
while(IndexesToBeRemoved.length) {
elements.splice(IndexesToBeRemoved.pop(), 1);
}
答案 3 :(得分:9)
我建议您使用Array.prototype.filter
var valuesArr = ["v1","v2","v3","v4","v5"];
var removeValFrom = [0, 2, 4];
valuesArr = valuesArr.filter(function(value, index) {
return removeValFrom.indexOf(index) == -1;
})
答案 4 :(得分:7)
function filtermethod(element, index, array) {
return removeValFromIndex.find(index)
}
var result = valuesArr.filter(filtermethod);
MDN参考是here
答案 5 :(得分:6)
在纯JS中,你可以向后遍历数组,因此splice()
不会弄乱循环中接下来元素的索引:
for (var i = arr.length - 1; i >= 0; i--) {
if ( yuck(arr[i]) ) {
arr.splice(i, 1);
}
}
答案 6 :(得分:5)
有必要在O(n)
时间:)发布答案。 splice解决方案的问题在于,由于数组的底层实现为literally an array,每个splice
调用将花费O(n)
时间。当我们设置一个利用此行为的示例时,这是最明显的:
var n = 100
var xs = []
for(var i=0; i<n;i++)
xs.push(i)
var is = []
for(var i=n/2-1; i>=0;i--)
is.push(i)
这会删除从中间到开头的元素,因此每次删除都会强制js引擎复制n/2
元素,我们总共有(n/2)^2
个复制操作,这是二次的。
拼接解决方案(假设is
已按降序排序以消除开销)如下所示:
for(var i=0; i<is.length; i++)
xs.splice(is[i], 1)
然而,实现线性时间解决方案并不难,通过从头开始重新构造数组,使用掩码来查看我们是否复制元素(sort会将其推送到O(n)log(n)
)。以下是这样的实现(不是mask
对于速度而言是布尔反转的):
var mask = new Array(xs.length)
for(var i=is.length - 1; i>=0; i--)
mask[is[i]] = true
var offset = 0
for(var i=0; i<xs.length; i++){
if(mask[i] === undefined){
xs[offset] = xs[i]
offset++
}
}
xs.length = offset
我在jsperf.com上运行此功能,即使n=100
,拼接方法也要慢90%。对于较大的n
,这种差异会更大。
答案 7 :(得分:2)
使用ES5的简单解决方案。这似乎更适合现在的大多数应用程序,因为许多应用程序不再需要依赖jQuery等。
当要删除的索引按升序排序时:
var valuesArr = ["v1", "v2", "v3", "v4", "v5"];
var removeValFromIndex = [0, 2, 4]; // ascending
removeValFromIndex.reverse().forEach(function(index) {
valuesArr.splice(index, 1);
});
当要删除的索引未排序时:
var valuesArr = ["v1", "v2", "v3", "v4", "v5"];
var removeValFromIndex = [2, 4, 0]; // unsorted
removeValFromIndex.sort(function(a, b) { return b - a; }).forEach(function(index) {
valuesArr.splice(index, 1);
});
答案 8 :(得分:2)
这对我来说很好,并且在从对象数组中删除时也可以工作:
var array = [
{ id: 1, name: 'bob', faveColor: 'blue' },
{ id: 2, name: 'jane', faveColor: 'red' },
{ id: 3, name: 'sam', faveColor: 'blue' }
];
// remove people that like blue
array.filter(x => x.faveColor === 'blue').forEach(x => array.splice(array.indexOf(x), 1));
也许可以写出一种更短,更有效的方法,但这确实有用。
答案 9 :(得分:1)
这是一种可能性:
valuesArr = removeValFromIndex.reduceRight(function (arr, it) {
arr.splice(it, 1);
return arr;
}, valuesArr.sort(function (a, b) { return b - a }));
答案 10 :(得分:1)
如果您使用的是underscore.js,则可以使用_.filter()
来解决问题。
var valuesArr = new Array("v1","v2","v3","v4","v5");
var removeValFromIndex = new Array(0,2,4);
var filteredArr = _.filter(valuesArr, function(item, index){
return !_.contains(removeValFromIndex, index);
});
此外,如果您尝试使用项目列表而不是索引删除项目,则可以使用_.without()
,如下所示:
var valuesArr = new Array("v1","v2","v3","v4","v5");
var filteredArr = _.without(valuesArr, "V1", "V3");
现在filteredArr
应为["V2", "V4", "V5"]
答案 11 :(得分:1)
function removeMany(array, indexes) {
return array.filter(function(_, idx) {
return indexes.indexOf(idx) === -1;
});
});
function removeMany(array, indexes = []) {
return array.filter((_, idx) => indexes.indexOf(idx) === -1)
}
答案 12 :(得分:1)
您可以将removeValFromIndex
替换为removeValFromIndex.reverse()
来更正您的代码。如果不保证该数组使用升序,则可以使用removeValFromIndex.sort(function(a, b) { return b - a })
。
答案 13 :(得分:1)
这里很快。
function removeFromArray(arr, toRemove){
return arr.filter(item => toRemove.indexOf(item) === -1)
}
const arr1 = [1, 2, 3, 4, 5, 6, 7]
const arr2 = removeFromArray(arr1, [2, 4, 6]) // [1,3,5,7]
答案 14 :(得分:0)
我建议您使用Array.prototype.filter
var valuesArr = ["v1","v2","v3","v4","v5"];
var removeValFrom = [0, 2, 4];
valuesArr = valuesArr.filter(function(value, index) {
return removeValFrom.indexOf(index) == -1;
}); // BIG O(N*m) where N is length of valuesArr and m is length removeValFrom
使用哈希......使用Array.prototype.map
var valuesArr = ["v1","v2","v3","v4","v5"];
var removeValFrom = {};
([0, 2, 4]).map(x=>removeValFrom[x]=1); //bild the hash.
valuesArr = valuesArr.filter(function(value, index) {
return removeValFrom[index] == 1;
}); // BIG O(N) where N is valuesArr;
答案 15 :(得分:0)
快速ES6一线:
const valuesArr = new Array("v1","v2","v3","v4","v5");
const removeValFromIndex = new Array(0,2,4);
const arrayWithValuesRemoved = valuesArr.filter((value, i) => removeValFromIndex.includes(i))
答案 16 :(得分:0)
var valuesArr = new Array("v1","v2","v3","v4","v5");
var removeValFromIndex = new Array(0,2,4);
console.log(valuesArr)
let arr2 = [];
for (let i = 0; i < valuesArr.length; i++){
if ( //could also just imput this below instead of index value
valuesArr[i] !== valuesArr[0] && // "v1" <--
valuesArr[i] !== valuesArr[2] && // "v3" <--
valuesArr[i] !== valuesArr[4] // "v5" <--
){
arr2.push(valuesArr[i]);
}
}
console.log(arr2);
这有效。但是,您将在此过程中创建一个新阵列。不知道那是否是您想要的,但是从技术上讲,它将是一个仅包含您想要的值的数组。
答案 17 :(得分:0)
使用filter和Set的简单有效的(线性复杂度)解决方案:
const valuesArr = ['v1', 'v2', 'v3', 'v4', 'v5'];
const removeValFromIndex = [0, 2, 4];
const indexSet = new Set(removeValFromIndex);
const arrayWithValuesRemoved = valuesArr.filter((value, i) => !indexSet.has(i));
console.log(arrayWithValuesRemoved);
该实现的最大优点是,设置查找操作(has
函数)需要固定的时间,例如比nevace的答案要快。
答案 18 :(得分:0)
removeValFromIndex.forEach(function(toRemoveIndex){
valuesArr.splice(toRemoveIndex,1);
});
答案 19 :(得分:0)
您可以尝试 Lodash js 库函数(_.forEach()
、_.remove()
)。我正在使用这种技术从表中删除多行。
let valuesArr = [
{id: 1, name: "dog"},
{id: 2, name: "cat"},
{id: 3, name: "rat"},
{id: 4, name: "bat"},
{id: 5, name: "pig"},
];
let removeValFromIndex = [
{id: 2, name: "cat"},
{id: 5, name: "pig"},
];
_.forEach(removeValFromIndex, (indi) => {
_.remove(valuesArr, (item) => {
return item.id === indi.id;
});
})
console.log(valuesArr)
/*[
{id: 1, name: "dog"},
{id: 3, name: "rat"},
{id: 4, name: "bat"},
];*/
在改变数组之前不要忘记克隆(_.clone(valuesArr)
或 [...valuesArr]
)
答案 20 :(得分:-1)
听起来Apply可能就是你要找的东西 也许像这样的东西会起作用吗?
Array.prototype.splice.apply(valuesArray, removeValFromIndexes );
答案 21 :(得分:-1)
您可以尝试使用delete array[index]
这不会完全删除元素,而是将值设置为undefined
。
答案 22 :(得分:-1)
您可以从数组构造一个Set
,然后从集合中创建一个数组。
const array = [1, 1, 2, 3, 5, 5, 1];
const uniqueArray = [...new Set(array)];
console.log(uniqueArray); // Result: [1, 2, 3, 5]
答案 23 :(得分:-1)
您可以使用 foreach 循环来执行此操作。
var valuesArr = new Array("v1","v2","v3","v4","v5");
var removeValFromIndex = new Array(0,2,4);
removeValFromIndex.forEach((value, index)=>{
valuesArr.splice(value, 1);
});
console.log(valuesArr);
另一种方法是您可以使用过滤器
let arr = [ 2, 3, 5, 8, 4 ];
let values = [ 2, 4 ];
arr = arr.filter(item => !values.includes(item));
console.log(arr);