[英]Remove multiple elements from array in Javascript/jQuery
I have two arrays.我有两个数组。 The first array contains some values while the second array contains indices of the values which should be removed from the first array.
第一个数组包含一些值,而第二个数组包含应该从第一个数组中删除的值的索引。 For example:
例如:
var valuesArr = new Array("v1","v2","v3","v4","v5");
var removeValFromIndex = new Array(0,2,4);
I want to remove the values present at indices 0,2,4
from valuesArr
.我想从
valuesArr
中删除索引0,2,4
处存在的值。 I thought the native splice
method might help so I came up with:我认为本机
splice
方法可能会有所帮助,所以我想出了:
$.each(removeValFromIndex,function(index,value){
valuesArr.splice(value,1);
});
But it didn't work because after each splice
, the indices of the values in valuesArr
were different.但它不起作用,因为在每次
splice
之后, valuesArr
中的值的索引都不同。 I could solve this problem by using a temporary array and copying all values to the second array, but I was wondering if there are any native methods to which we can pass multiple indices at which to remove values from an array.我可以通过使用临时数组并将所有值复制到第二个数组来解决这个问题,但我想知道是否有任何本机方法可以传递多个索引来从数组中删除值。
I would prefer a jQuery solution.我更喜欢 jQuery 解决方案。 (Not sure if I can use
grep
here) (不确定我是否可以在这里使用
grep
)
There's always the plain old for
loop:总是有普通的旧
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);
Go through removeValFromIndex
in reverse order and you can .splice()
without messing up the indexes of the yet-to-be-removed items.以相反的顺序遍历
removeValFromIndex
,您可以.splice()
而不会弄乱尚未删除的项目的索引。
Note in the above I've used the array-literal syntax with square brackets to declare the two arrays.请注意,在上面我使用了带有方括号的数组文字语法来声明两个数组。 This is the recommended syntax because
new Array()
use is potentially confusing given that it responds differently depending on how many parameters you pass in.这是推荐的语法,因为
new Array()
的使用可能会令人困惑,因为它的响应取决于您传入的参数数量。
EDIT : Just saw your comment on another answer about the array of indexes not necessarily being in any particular order.编辑:刚刚看到您对关于索引数组不一定按任何特定顺序的另一个答案的评论。 If that's the case just sort it into descending order before you start:
如果是这种情况,只需在开始之前将其按降序排序:
removeValFromIndex.sort(function(a,b){ return b - a; });
And follow that with whatever looping / $.each()
/ etc. method you like.并按照您喜欢的任何循环 /
$.each()
/ 等方法进行。
I suggest you use Array.prototype.filter我建议你使用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;
})
Here is one that I use when not going with lodash/underscore:这是我在不使用 lodash/underscore 时使用的一个:
while(IndexesToBeRemoved.length) {
elements.splice(IndexesToBeRemoved.pop(), 1);
}
A simple and efficient (linear complexity) solution using filter and Set :使用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);
The great advantage of that implementation is that the Set lookup operation ( has
function) takes a constant time, being faster than nevace's answer, for example.该实现的最大优点是 Set 查找操作 (
has
函数) 需要一个恒定的时间,例如比 nevace 的答案更快。
This works well for me and work when deleting from an array of objects too:这对我很有效,并且在从对象数组中删除时也有效:
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));
There might be a shorter more effecient way to write this but this does work.可能有一种更短更有效的方法来编写它,但这确实有效。
It feels necessary to post an answer with O(n)
time :).感觉有必要用
O(n)
时间发布答案:)。 The problem with the splice solution is that due to the underlying implementation of array being literally an array , each splice
call will take O(n)
time.拼接解决方案的问题在于,由于 array 的底层实现实际上是一个 array ,每个
splice
调用将花费O(n)
时间。 This is most pronounced when we setup an example to exploit this behavior:当我们设置一个示例来利用此行为时,这一点最为明显:
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)
This removes elements starting from the middle to the start, hence each remove forces the js engine to copy n/2
elements, we have (n/2)^2
copy operations in total which is quadratic.这会删除从中间到开始的元素,因此每次删除都会强制 js 引擎复制
n/2
元素,我们总共有(n/2)^2
复制操作,这是二次的。
The splice solution (assuming is
is already sorted in decreasing order to get rid of overheads) goes like this:拼接解决方案(假设
is
已经按降序排序以消除开销)如下所示:
for(var i=0; i<is.length; i++)
xs.splice(is[i], 1)
However, it is not hard to implement a linear time solution, by re-constructing the array from scratch, using a mask to see if we copy elements or not (sort will push this to O(n)log(n)
).然而,实现线性时间解决方案并不难,通过从头开始重新构造数组,使用掩码查看我们是否复制元素(排序会将其推送到
O(n)log(n)
)。 The following is such an implementation (not that mask
is boolean inverted for speed):以下是这样一个实现(不是为了速度而将
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
I ran this on jsperf.com and for even n=100
the splice method is a full 90% slower.我在jsperf.com上运行了这个,即使
n=100
,拼接方法也慢了 90%。 For larger n
this difference will be much greater.对于较大的
n
,这种差异会更大。
In pure JS you can loop through the array backwards, so splice()
will not mess up indices of the elements next in the loop:在纯 JS 中,您可以向后循环数组,因此
splice()
不会弄乱循环中下一个元素的索引:
for (var i = arr.length - 1; i >= 0; i--) {
if ( yuck(arr[i]) ) {
arr.splice(i, 1);
}
}
A simple solution using ES5.使用 ES5 的简单解决方案。 This seems more appropriate for most applications nowadays, since many do no longer want to rely on jQuery etc.
这似乎更适合现在的大多数应用程序,因为许多应用程序不再想依赖 jQuery 等。
When the indexes to be removed are sorted in ascending order:当要删除的索引按升序排序时:
var valuesArr = ["v1", "v2", "v3", "v4", "v5"];
var removeValFromIndex = [0, 2, 4]; // ascending
removeValFromIndex.reverse().forEach(function(index) {
valuesArr.splice(index, 1);
});
When the indexes to be removed are not sorted:当要删除的索引没有排序时:
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);
});
Quick ES6 one liner:快速 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))
If you are using underscore.js , you can use _.filter()
to solve your problem.如果你使用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);
});
Additionally, if you are trying to remove items using a list of items instead of indexes, you can simply use _.without()
, like so:此外,如果您尝试使用项目列表而不是索引来删除项目,则可以简单地使用
_.without()
,如下所示:
var valuesArr = new Array("v1","v2","v3","v4","v5");
var filteredArr = _.without(valuesArr, "V1", "V3");
Now filteredArr
should be ["V2", "V4", "V5"]
现在
filteredArr
应该是["V2", "V4", "V5"]
I find this the most elegant solution:我发现这是最优雅的解决方案:
const oldArray = [1, 2, 3, 4, 5]
const removeItems = [1, 3, 5]
const newArray = oldArray.filter((value) => {
return !removeItems.includes(value)
})
console.log(newArray)
output:输出:
[2, 4]
Here's one possibility:这是一种可能性:
valuesArr = removeValFromIndex.reduceRight(function (arr, it) {
arr.splice(it, 1);
return arr;
}, valuesArr.sort(function (a, b) { return b - a }));
Example on jsFiddle jsFiddle 上的示例
MDN on Array.prototype.reduceRight Array.prototype.reduceRight 上的 MDN
filter + indexOf (IE9+): 过滤器+ indexOf (IE9+):
function removeMany(array, indexes) {
return array.filter(function(_, idx) {
return indexes.indexOf(idx) === -1;
});
});
Or with ES6 filter + find (Edge+):或者使用 ES6 过滤器+ 查找(Edge+):
function removeMany(array, indexes = []) {
return array.filter((_, idx) => indexes.indexOf(idx) === -1)
}
Here's a quickie.这是一个快速的。
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]
You can correct your code by replacing removeValFromIndex
with removeValFromIndex.reverse()
.您可以通过将
removeValFromIndex
替换为removeValFromIndex.reverse()
来更正您的代码。 If that array is not guaranteed to use ascending order, you can instead use removeValFromIndex.sort(function(a, b) { return b - a })
.如果该数组不能保证使用升序,您可以改用
removeValFromIndex.sort(function(a, b) { return b - a })
。
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);
This works.这行得通。 However, you would make a new array in the process.
但是,您将在此过程中创建一个新数组。 Not sure if thats would you want or not, but technically it would be an array containing only the values you wanted.
不确定您是否想要,但从技术上讲,它将是一个仅包含您想要的值的数组。
You can try Lodash js library functions ( _.forEach()
, _.remove()
).您可以尝试 Lodash js 库函数(
_.forEach()
, _.remove()
)。 I was using this technique to remove multiple rows from the table.我正在使用这种技术从表中删除多行。
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"},
];*/
Don't forget to clone ( _.clone(valuesArr)
or [...valuesArr]
) before mutate your array在改变数组之前不要忘记克隆(
_.clone(valuesArr)
或[...valuesArr]
)
Try this尝试这个
var valuesArr = new Array("v1", "v2", "v3", "v4", "v5"); console.info("Before valuesArr = " + valuesArr); var removeValFromIndex = new Array(0, 2, 4); valuesArr = valuesArr.filter((val, index) => { return !removeValFromIndex.includes(index); }) console.info("After valuesArr = " + valuesArr);
removeValFromIndex.forEach(function(toRemoveIndex){
valuesArr.splice(toRemoveIndex,1);
});
You can use foreach loop to do so.您可以使用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);
Another way is You can use the filter另一种方法是您可以使用过滤器
let arr = [ 2, 3, 5, 8, 4 ];
let values = [ 2, 4 ];
arr = arr.filter(item => !values.includes(item));
console.log(arr);
您可以尝试使用delete array[index]
这不会完全删除元素,而是将值设置为undefined
。
I suggest you use Array.prototype.filter我建议你使用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
with Hashes... using Array.prototype.map使用哈希...使用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;
You could construct a Set
from the array and then create an array from the set.您可以从数组构造一个
Set
,然后从该集合创建一个数组。
const array = [1, 1, 2, 3, 5, 5, 1];
const uniqueArray = [...new Set(array)];
console.log(uniqueArray); // Result: [1, 2, 3, 5]
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.