javascript - splice用法 - js splice
如何從JavaScript中刪除數組中的特定元素? (20)
我有一個整數數組,我正在使用.push()
方法向其中添加元素。
有沒有一種簡單的方法從數組中刪除特定元素? 相當於像array.remove(int);
。
我必須使用核心 JavaScript - 不允許使用框架。
ES6和無突變:( 2016年10月)
const removeByIndex = (list, index) =>
[
...list.slice(0, index),
...list.slice(index + 1)
];
然後 :
removeByIndex([33,22,11,44],1) //=> [33,11,44]
編輯於2016年10月
- 做到簡單,直觀和明確( https://en.wikipedia.org/wiki/Occam%27s_razor )
- 做它是不可變的(原始數組保持不變)
- 使用標準JS函數,如果您的瀏覽器不支持它們 - 使用polyfill
在這個代碼示例中,我使用“array.filter(...)”函數從數組中刪除不需要的項,此函數不會更改原始數組並創建新數組。 如果您的瀏覽器不支持此功能(例如版本9之前的IE或版本1.5之前的Firefox),請考慮使用Mozilla中的過濾器polyfill 。
刪除項目(ECMA-262 Edition 5 code aka oldstyle JS)
var value = 3
var arr = [1, 2, 3, 4, 5, 3]
arr = arr.filter(function(item) {
return item !== value
})
console.log(arr)
// [ 1, 2, 4, 5 ]
刪除項目(ES2015代碼)
let value = 3
let arr = [1, 2, 3, 4, 5, 3]
arr = arr.filter(item => item !== value)
console.log(arr)
// [ 1, 2, 4, 5 ]
重要事項 ES2015“()=> {}”IE中根本不支持箭頭功能語法,Chrome版本為45版本,Firefox版本為22版本,Safari版本為10版本。 要在舊瀏覽器中使用ES2015語法,您可以使用BabelJS
刪除多個項目(ES2016代碼)
此方法的另一個優點是您可以刪除多個項目
let forDeletion = [2, 3, 5]
let arr = [1, 2, 3, 4, 5, 3]
arr = arr.filter(item => !forDeletion.includes(item))
// !!! Read below about array.includes(...) support !!!
console.log(arr)
// [ 1, 4 ]
重要信息 IE中根本不支持“array.includes(...)”功能,47版本之前的Chrome版本,43版本之前的Firefox版本,9版本之前的Safari版本以及14版本之前的Edge版本所以這裡是來自Mozilla的polyfill
刪除多個項目(尖端實驗性JavaScript ES2018?)
// array-lib.js
export function remove(...forDeletion) {
return this.filter(item => !forDeletion.includes(item))
}
// main.js
import { remove } from './array-lib.js'
let arr = [1, 2, 3, 4, 5, 3]
// :: This-Binding Syntax Proposal
// using "remove" function as "virtual method"
// without extending Array.prototype
arr = arr::remove(2, 3, 5)
console.log(arr)
// [ 1, 4 ]
參考
Underscore.js可用於解決多個瀏覽器的問題。 它使用內置瀏覽器方法(如果存在)。 如果它們不存在,就像舊的Internet Explorer版本一樣,它使用自己的自定義方法。
從數組中刪除元素的簡單示例(來自網站):
_.without([1, 2, 1, 0, 3, 1, 4], 0, 1); // => [2, 3, 4]
好的,例如你有以下數組:
var num = [1, 2, 3, 4, 5];
我們想刪除4號,你可以簡單地做下面的代碼:
num.splice(num.indexOf(4), 1); //num will be [1, 2, 3, 5];
如果重新使用此函數,則編寫一個可重用的函數,該函數將附加到Native數組函數,如下所示:
Array.prototype.remove = Array.prototype.remove || function(x) {
const i = this.indexOf(x);
if(i===-1) return;
this.splice(i, 1); //num.remove(5) === [1, 2, 3];
}
但是,如果您使用下面的數組而不是數組中的[5] s,那怎麼樣?
var num = [5, 6, 5, 4, 5, 1, 5];
我們需要一個循環來檢查所有這些,但更容易和更有效的方法是使用內置的JavaScript函數,所以我們編寫一個使用過濾器的函數,如下所示:
const _removeValue = (arr, x) => arr.filter(n => n!==x);
//_removeValue([1, 2, 3, 4, 5, 5, 6, 5], 5) //return [1, 2, 3, 4, 6]
還有第三方庫可以幫助你做這些,比如Lodash或Underscore,有關更多信息,請查看lodash _.pull,_.pullAt或_.without。
一位朋友在Internet Explorer 8遇到問題,並向我展示了他的所作所為。 我告訴他這是錯的,他告訴我他在這裡得到了答案。 當前的最佳答案不適用於所有瀏覽器(例如Internet Explorer 8),它只會刪除第一次出現的項目。
從數組中刪除所有實例
function remove(arr, item) {
for (var i = arr.length; i--;) {
if (arr[i] === item) {
arr.splice(i, 1);
}
}
}
它向後循環遍歷數組(因為索引和長度將隨著項目的移除而改變)並刪除項目(如果已找到)。 它適用於所有瀏覽器。
以下是使用JavaScript從數組中刪除項目的幾種方法。
所描述的所有方法都不會改變原始數組 ,而是創建一個新數組 。
如果您知道項目的索引
假設您有一個數組,並且想要移除位置i
中的項目。
一種方法是使用slice()
:
const items = ['a', 'b', 'c', 'd', 'e', 'f']
const i = 3
const filteredItems = items.slice(0, i-1).concat(items.slice(i, items.length))
console.log(filteredItems)
slice()
使用它接收的索引創建一個新數組。 我們只是創建一個新數組,從開始到我們想要刪除的索引,並從我們刪除的數據到數組末尾之後的第一個位置連接另一個數組。
如果你知道價值
在這種情況下,一個不錯的選擇是使用filter()
,它提供了更具說明性的方法:
const items = ['a', 'b', 'c', 'd', 'e', 'f']
const valueToRemove = 'c'
const filteredItems = items.filter(item => item !== valueToRemove)
console.log(filteredItems)
這使用ES6箭頭功能。 您可以使用傳統功能來支持舊版瀏覽器:
const items = ['a', 'b', 'c', 'd', 'e', 'f']
const valueToRemove = 'c'
const filteredItems = items.filter(function(item) {
return item !== valueToRemove
})
console.log(filteredItems)
或者您可以使用Babel並將ES6代碼轉發回ES5,使其更易於瀏覽舊瀏覽器,同時在代碼中編寫現代JavaScript。
刪除多個項目
如果不是單個項目,您想要刪除多個項目,該怎麼辦?
讓我們找到最簡單的解決方案。
按索引
您只需創建一個函數並刪除系列中的項目:
const items = ['a', 'b', 'c', 'd', 'e', 'f']
const removeItem = (items, i) =>
items.slice(0, i-1).concat(items.slice(i, items.length))
let filteredItems = removeItem(items, 3)
filteredItems = removeItem(filteredItems, 5)
//["a", "b", "c", "d"]
console.log(filteredItems)
按價值
您可以在回調函數中搜索包含:
const items = ['a', 'b', 'c', 'd', 'e', 'f']
const valuesToRemove = ['c', 'd']
const filteredItems = items.filter(item => !valuesToRemove.includes(item))
// ["a", "b", "e", "f"]
console.log(filteredItems)
避免改變原始數組
splice()
(不要與slice()
混淆)改變原始數組,應該避免。
(最初發佈於https://flaviocopes.com/how-to-remove-item-from-array/ )
你有1到9個數組,你想刪除5使用下面的代碼。
var numberArray = [1, 2, 3, 4, 5, 6, 7, 8, 9];
var newNumberArray = numberArray.filter(m => {
return m !== 5;
});
console.log("new Array, 5 removed", newNumberArray);
如果你想要多個值ex: - 1,7,8
var numberArray = [1, 2, 3, 4, 5, 6, 7, 8, 9];
var newNumberArray = numberArray.filter(m => {
return (m !== 1) && (m !== 7) && (m !== 8);
});
console.log("new Array, 5 removed", newNumberArray);
如果要刪除數組ex中的數組值: - [3,4,5]
var numberArray = [1, 2, 3, 4, 5, 6, 7, 8, 9];
var removebleArray = [3,4,5];
var newNumberArray = numberArray.filter(m => {
return !removebleArray.includes(m);
});
console.log("new Array, [3,4,5] removed", newNumberArray);
包括支持的瀏覽器是link
你永遠不應該在你的數組中改變你的數組。 因為這是針對功能編程模式的。 你可以做的是創建一個新的數組,而不引用你想要使用es6方法filter
更改數據的數組;
var myArray = [1,2,3,4,5,6];
假設您要從數組中刪除5
,您可以像這樣簡單地執行此操作。
myArray = myArray.filter(value => value !== 5);
這將為您提供一個沒有您想要刪除的值的新數組。 結果將是
[1,2,3,4,6]; // 5 has been removed from this array
為了進一步理解,您可以閱讀Array.filter上的MDN文檔filter
基於所有主要正確的答案並考慮到建議的最佳實踐(特別是不直接使用Array.prototype),我想出了以下代碼:
function arrayWithout(arr, values) {
var isArray = function(canBeArray) {
if (Array.isArray) {
return Array.isArray(canBeArray);
}
return Object.prototype.toString.call(canBeArray) === '[object Array]';
};
var excludedValues = (isArray(values)) ? values : [].slice.call(arguments, 1);
var arrCopy = arr.slice(0);
for (var i = arrCopy.length - 1; i >= 0; i--) {
if (excludedValues.indexOf(arrCopy[i]) > -1) {
arrCopy.splice(i, 1);
}
}
return arrCopy;
}
回顧上述功能,儘管它工作正常,但我意識到可能會有一些性能提升。使用ES6而不是ES5也是一種更好的方法。為此,這是改進的代碼:
const arrayWithoutFastest = (() => {
const isArray = canBeArray => ('isArray' in Array)
? Array.isArray(canBeArray)
: Object.prototype.toString.call(canBeArray) === '[object Array]';
let mapIncludes = (map, key) => map.has(key);
let objectIncludes = (obj, key) => key in obj;
let includes;
function arrayWithoutFastest(arr, ...thisArgs) {
let withoutValues = isArray(thisArgs[0]) ? thisArgs[0] : thisArgs;
if (typeof Map !== 'undefined') {
withoutValues = withoutValues.reduce((map, value) => map.set(value, value), new Map());
includes = mapIncludes;
} else {
withoutValues = withoutValues.reduce((map, value) => { map[value] = value; return map; } , {});
includes = objectIncludes;
}
const arrCopy = [];
const length = arr.length;
for (let i = 0; i < length; i++) {
// If value is not in exclude list
if (!includes(withoutValues, arr[i])) {
arrCopy.push(arr[i]);
}
}
return arrCopy;
}
return arrayWithoutFastest;
})();
如何使用:
const arr = [1,2,3,4,5,"name", false];
arrayWithoutFastest(arr, 1); // will return array [2,3,4,5,"name", false]
arrayWithoutFastest(arr, 'name'); // will return [2,3,4,5, false]
arrayWithoutFastest(arr, false); // will return [2,3,4,5]
arrayWithoutFastest(arr,[1,2]); // will return [3,4,5,"name", false];
arrayWithoutFastest(arr, {bar: "foo"}); // will return the same array (new copy)
我目前正在撰寫一篇博文,其中我對Array的幾個解決方案進行了基準測試,沒有遇到任何問題,並比較了運行所需的時間。完成該帖後,我將使用鏈接更新此答案。只是為了讓你知道,我已經將上面的內容與lodash的內容進行了比較,如果瀏覽器不支持Map
,它就勝過了lodash!請注意,我沒有使用Array.prototype.indexOf
或Array.prototype.includes
包含exlcudeValues Map
或Object
更快地查詢!(https://jsperf.com/array-without-benchmark-against-lodash)
太老了回复,但可能通過提供謂詞而不是值來幫助某人。
注意:它將更新給定的數組,並返回受影響的行
用法
var removed = helper.removeOne(arr, row => row.id === 5 );
var removed = helper.remove(arr, row => row.name.startsWith('BMW'));
定義
var helper = {
// Remove and return the first occurrence
removeOne: function(array, predicate) {
for (var i = 0; i < array.length; i++) {
if (predicate(array[i])) {
return array.splice(i, 1);
}
}
},
// Remove and return all occurrences
remove: function(array, predicate) {
var removed = [];
for (var i = 0; i < array.length;) {
if (predicate(array[i])) {
removed.push(array.splice(i, 1));
continue;
}
i++;
}
return removed;
}
};
如果要刪除已刪除位置的新數組,可以始終刪除特定元素並過濾掉數組。 對於沒有實現過濾方法的瀏覽器,可能需要對數組對象進行擴展,但從長遠來看,它更容易,因為你所做的只是:
var my_array = [1,2,3,4,5,6];
delete my_array[4];
console.log(my_array.filter(function(a){return typeof a !== 'undefined';}));
應該顯示[1, 2, 3, 4, 6]
如果陣列中有復雜對象,可以使用過濾器嗎? 在$ .inArray或array.splice不那麼容易使用的情況下。 特別是如果對像在數組中可能很淺。
例如,如果您有一個帶有Id字段的對象,並且您希望從數組中刪除該對象:
this.array = this.array.filter(function(element, i) {
return element.id !== idToRemove;
});
您可以使用ES6。
var array=['1','2','3','4','5','6']
var index = array.filter((value)=>value!='3');
輸出:
["1", "2", "4", "5", "6"]
我不知道你期望array.remove(int)
如何表現。 我可以想到你可能想要的三種可能性。
要在索引i
處刪除數組的元素:
array.splice(i, 1);
如果要從數組中刪除具有值number
每個元素:
for(var i = array.length - 1; i >= 0; i--) {
if(array[i] === number) {
array.splice(i, 1);
}
}
如果您只想使索引i
處的元素不再存在,但您不希望其他元素的索引發生更改:
delete array[i];
我還有另一個從數組中刪除的好方法:
var words = ['spray', 'limit', 'elite', 'exuberant', 'destruction', 'present'];
const result = words.filter(word => word.length > 6);
console.log(result);
// expected output: Array ["exuberant", "destruction", "present"]
找到要刪除的數組元素的index
,然後使用splice
刪除該索引。
splice()方法通過刪除現有元素和/或添加新元素來更改數組的內容。
var array = [2, 5, 9];
console.log(array)
var index = array.indexOf(5);
if (index > -1) {
array.splice(index, 1);
}
// array = [2, 9]
console.log(array);
splice
的第二個參數是要刪除的元素數。 請注意, splice
會修改數組並返回一個包含已刪除元素的新數組。
注意 : 對indexOf的瀏覽器支持有限; Internet Explorer 7和8不支持它。
如果您在不受支持的瀏覽器中需要indexOf
,請嘗試以下polyfill
。 在此處查找有關此polyfill
更多信息。
Array.prototype.indexOf || (Array.prototype.indexOf = function(d, e) {
var a;
if (null == this) throw new TypeError('"this" is null or not defined');
var c = Object(this),
b = c.length >>> 0;
if (0 === b) return -1;
a = +e || 0;
Infinity === Math.abs(a) && (a = 0);
if (a >= b) return -1;
for (a = Math.max(0 <= a ? a : b - Math.abs(a), 0); a < b;) {
if (a in c && c[a] === d) return a;
a++
}
return -1
});
有兩種主要方法:
splice() :
anArray.splice(index, 1);
刪除 :
delete anArray[index];
對數組使用delete時要小心。 刪除對象的屬性很好,但對數組不太好。 最好將splice
用於數組。
請記住,當您對數組使用delete
時, anArray.length
可能會得到錯誤的結果。 換句話說, delete
將刪除元素但不會更新length屬性的值。
使用刪除後,您還可能會在索引號中出現漏洞,例如,您最終可能會使用刪除之前的索引1,3,4,8,9,11和長度。 在這種情況下,所有索引for
循環都會崩潰,因為索引不再是順序的。
如果由於某種原因被迫使用delete
,那麼當需要循環遍歷數組時,應該使用for each
循環。 事實上,如果可能的話,總是避免使用索引for循環。 這樣,代碼將更加健壯,並且不易出現索引問題。
無需使用indexOf
或splice
。 但是,如果您只想刪除一個元素,它會表現得更好。
查找並移動(移動):
function move(arr, val) {
var j = 0;
for (var i = 0, l = arr.length; i < l; i++) {
if (arr[i] !== val) {
arr[j++] = arr[i];
}
}
arr.length = j;
}
使用indexOf
和splice
(indexof):
function indexof(arr, val) {
var i;
while ((i = arr.indexOf(val)) != -1) {
arr.splice(i, 1);
}
}
僅使用splice
(拼接):
function splice(arr, val) {
for (var i = arr.length; i--;) {
if (arr[i] === val) {
arr.splice(i, 1);
}
}
}
nodejs上運行時間為1000個元素(平均超過10000次運行)的數組:
indexof比移動慢大約10倍。 即使通過在splice中刪除對indexOf
的調用來改進它,它也比移動更糟糕。
Remove all occurrences:
move 0.0048 ms
indexof 0.0463 ms
splice 0.0359 ms
Remove first occurrence:
move_one 0.0041 ms
indexof_one 0.0021 ms
我知道已有很多答案,但其中許多似乎使問題複雜化。這是一種刪除鍵的所有實例的簡單遞歸方法 - 調用self直到找不到索引。是的,它只能在瀏覽器中使用indexOf
,但它很簡單,可以很容易地填充。
獨立功能
function removeAll(array, key){
var index = array.indexOf(key);
if(index === -1) return;
array.splice(index, 1);
removeAll(array,key);
}
原型方法
Array.prototype.removeAll = function(key){
var index = this.indexOf(key);
if(index === -1) return;
this.splice(index, 1);
this.removeAll(key);
}
Array.prototype.removeItem = function(a) {
for (i = 0; i < this.length; i++) {
if (this[i] == a) {
for (i2 = i; i2 < this.length - 1; i2++) {
this[i2] = this[i2 + 1];
}
this.length = this.length - 1
return;
}
}
}
var recentMovies = ['Iron Man', 'Batman', 'Superman', 'Spiderman'];
recentMovies.removeItem('Superman');