Як видалити порожні елементи з масиву в JavaScript?
Чи є прямий спосіб, чи мені потрібно провести цикл через нього та видалити їх вручну?
Як видалити порожні елементи з масиву в JavaScript?
Чи є прямий спосіб, чи мені потрібно провести цикл через нього та видалити їх вручну?
Відповіді:
EDIT: На це питання відповіли майже дев'ять років тому, коли в програмі не було багато корисних вбудованих методів Array.prototype
.
Тепер, звичайно, я б рекомендував вам скористатися filter
методом.
Майте на увазі, що цей метод поверне вам новий масив з елементами, які передають критерії функції зворотного виклику, яку ви йому надаєте.
Наприклад, якщо ви хочете видалити null
або вказати undefined
значення:
var array = [0, 1, null, 2, "", 3, undefined, 3,,,,,, 4,, 4,, 5,, 6,,,,];
var filtered = array.filter(function (el) {
return el != null;
});
console.log(filtered);
Це залежатиме від того, що ви вважаєте "порожнім", наприклад, якщо ви мали справу з рядками, наведена вище функція не видалить елементи, які є порожнім рядком.
Один типовий зразок , який я бачу часто використовується для видалення елементів , які є falsy , які включають в порожній рядок ""
, 0
, NaN
, null
, undefined
, і false
.
Ви можете перейти до filter
методу, функції Boolean
конструктора або повернути той самий елемент у функції критеріїв фільтра, наприклад:
var filtered = array.filter(Boolean);
Або
var filtered = array.filter(function(el) { return el; });
В обох випадках це працює, тому що filter
метод у першому випадку викликає Boolean
конструктор як функцію, перетворюючи значення, а у другому випадку filter
метод внутрішньо повертає повернене значення зворотного виклику неявно Boolean
.
Якщо ви працюєте з розрідженими масивами, і ви намагаєтеся позбутися "дірок", ви можете використовувати filter
метод передачі зворотного виклику, який повертає істину, наприклад:
var sparseArray = [0, , , 1, , , , , 2, , , , 3],
cleanArray = sparseArray.filter(function () { return true });
console.log(cleanArray); // [ 0, 1, 2, 3 ]
Стара відповідь: Не робіть цього!
Я використовую цей метод, розширюючи власний прототип масиву:
Array.prototype.clean = function(deleteValue) {
for (var i = 0; i < this.length; i++) {
if (this[i] == deleteValue) {
this.splice(i, 1);
i--;
}
}
return this;
};
test = new Array("", "One", "Two", "", "Three", "", "Four").clean("");
test2 = [1, 2,, 3,, 3,,,,,, 4,, 4,, 5,, 6,,,,];
test2.clean(undefined);
Або ви можете просто натиснути наявні елементи в інший масив:
// Will remove all falsy values: undefined, null, 0, false, NaN and "" (empty string)
function cleanArray(actual) {
var newArray = new Array();
for (var i = 0; i < actual.length; i++) {
if (actual[i]) {
newArray.push(actual[i]);
}
}
return newArray;
}
cleanArray([1, 2,, 3,, 3,,,,,, 4,, 4,, 5,, 6,,,,]);
splice
Виклик дійсно дорого на старих браузерах , тому що вони повинні пронумерувати всі ключі масиву , щоб закрити цю прогалину.
Array.prototype
використання, Object.defineProperty
щоб зробити нову функцію незліченною властивістю, а потім уникнути хітів продуктивності, спричинених введенням .hasOwnProperty
у кожен цикл.
var arr = [1,2,,3,,-3,null,,0,,undefined,4,,4,,5,,6,,,,];
arr.filter(n => n)
// [1, 2, 3, -3, 4, 4, 5, 6]
arr.filter(Number)
// [1, 2, 3, -3, 4, 4, 5, 6]
arr.filter(Boolean)
// [1, 2, 3, -3, 4, 4, 5, 6]
або - (лише для окремих елементів масиву типу "текст")
['','1','2',3,,'4',,undefined,,,'5'].join('').split('');
// output: ["1","2","3","4","5"]
або - Класичний спосіб: проста ітерація
var arr = [1,2,null, undefined,3,,3,,,0,,,[],,{},,5,,6,,,,],
len = arr.length, i;
for(i = 0; i < len; i++ )
arr[i] && arr.push(arr[i]); // copy non-empty values to the end of the array
arr.splice(0 , len); // cut the array and leave only the non-empty values
arr // [1,2,3,3,[],Object{},5,6]
var arr = [1,2,,3,,3,,,0,,,4,,4,,5,,6,,,,];
arr = $.grep(arr,function(n){ return n == 0 || n });
arr // [1, 2, 3, 3, 0, 4, 4, 5, 6]
var arr = [1,2,null, undefined,3,,3,,,0,,,4,,4,,5,,6,,,,],
temp = [];
for(let i of arr)
i && temp.push(i); // copy each non-empty value to the 'temp' array
arr = temp;
arr // [1, 2, 3, 3, 4, 4, 5, 6]
['foo', '',,,'',,null, ' ', 3, true, [], [1], {}, undefined, ()=>{}].filter(String)
// ["foo", null, " ", 3, true, [1], Object {}, undefined, ()=>{}]
arr = arr.filter(function(n){return n; });
foo.join("").split("")
Здається, працює лише в тому випадку, якщо рядки є єдиними символами
arr.filter(e=>e)
і це можна
Якщо вам потрібно видалити ВСІ порожні значення ("", null, undefined та 0):
arr = arr.filter(function(e){return e});
Щоб видалити порожні значення та розриви рядків:
arr = arr.filter(function(e){ return e.replace(/(\r\n|\n|\r)/gm,"")});
Приклад:
arr = ["hello",0,"",null,undefined,1,100," "]
arr.filter(function(e){return e});
Повернення:
["hello", 1, 100, " "]
ОНОВЛЕННЯ (на основі коментаря Alnitak)
У деяких ситуаціях ви можете зберегти "0" в масиві та видалити що-небудь інше (null, undefined and ""), це один із способів:
arr.filter(function(e){ return e === 0 || e });
Повернення:
["hello", 0, 1, 100, " "]
function(e){return !!e}
!!e
буде включати NaN (на відміну від 0), де e
не буде (як 0).
var myarr=[1, 2,, 3,, 3,undefined,,"",,0, 4,, 4,, 5,, 6,,,,].filter(Boolean);
видаляє невизначені, "" та 0
Просто один вкладиш:
[1, false, "", undefined, 2].filter(Boolean); // [1, 2]
або за допомогою underscorejs.org :
_.filter([1, false, "", undefined, 2], Boolean); // [1, 2]
// or even:
_.compact([1, false, "", undefined, 2]); // [1, 2]
Boolean
працює як функція ...
Boolean
як функцію, вона просто поверне true
або false
зміцнить значення по-справжньому / помилково.
(true).constructor === Boolean
. А потім скажіть, чи можемо ми це зробити за допомогою інших вбудованих програм в JS. ;)) (звичайно виключаються інші 5 вбудованих конструкторів. (Рядок, масив, об'єкт, функція, число))
Якщо у вас Javascript 1.6 або пізнішої версії, ви можете використовувати Array.filter
за допомогою тривіальної return true
функції зворотного виклику, наприклад:
arr = arr.filter(function() { return true; });
оскільки .filter
автоматично пропускає відсутні елементи в початковому масиві.
Сторінка MDN, пов'язана вище, також містить приємну версію перевірки помилок, filter
яку можна використовувати в інтерпретаторах JavaScript, які не підтримують офіційну версію.
Зауважте, що це не буде видаляти null
записи та записи з явним undefined
значенням, але ОП спеціально вимагає "відсутні" записи.
undefined
якості заданого значення.
Для видалення отворів слід використовувати
arr.filter(() => true)
arr.flat(0) // Currently stage 3, check compatibility before using this
Для видалення отвору та значень фальш (null, undefined, 0, -0, NaN, "", false, document.all):
arr.filter(x => x)
Для видалення отвору, null та, undefined:
arr.filter(x => x != null)
arr = [, null, (void 0), 0, -0, NaN, false, '', 42];
console.log(arr.filter(() => true)); // [null, (void 0), 0, -0, NaN, false, '', 42]
console.log(arr.filter(x => x)); // [42]
console.log(arr.filter(x => x != null)); // [0, -0, NaN, false, "", 42]
[, ,]
arr.filter(x => x)
, JS перевірить, чи х є правдою чи хибністю, тобто if (x)
, тому нове перелік буде присвоєно лише значення трикути.
Чистий спосіб це зробити.
var arr = [0,1,2,"Thomas","false",false,true,null,3,4,undefined,5,"end"];
arr = arr.filter(Boolean);
// [1, 2, "Thomas", "false", true, 3, 4, 5, "end"]
undefined
; це в основному видаляє всі помилкові значення.
З підкресленням / Лодаш:
Загальний випадок використання:
_.without(array, emptyVal, otherEmptyVal);
_.without([1, 2, 1, 0, 3, 1, 4], 0, 1);
З порожніми місцями:
_.without(['foo', 'bar', '', 'baz', '', '', 'foobar'], '');
--> ["foo", "bar", "baz", "foobar"]
Дивіться документацію lodash для без .
Просто ES6
і новіші версії методу, припустимо, масив нижче:
const arr = [1,2,3,undefined,4,5,6,undefined,7,8,undefined,undefined,0,9];
Простий спосіб:
const clearArray = arr.filter( i => i );
Якщо використання бібліотеки - це варіант, я знаю, що underscore.js має функцію, що називається компактний () http://documentcloud.github.com/underscore/, він також має кілька інших корисних функцій, пов'язаних з масивами та колекціями.
Ось уривок з їх документації:
_.compact (масив)
Повертає копію масиву із видаленими фальшивими значеннями. У JavaScript, false, null, 0, "", undefined та NaN - все помилково.
_.compact ([0, 1, false, 2, '', 3]);
=> [1, 2, 3]
@Alnitak
Насправді Array.filter працює у всіх браузерах, якщо додати додатковий код. Дивись нижче.
var array = ["","one",0,"",null,0,1,2,4,"two"];
function isempty(x){
if(x!=="")
return true;
}
var res = array.filter(isempty);
document.writeln(res.toJSONString());
// gives: ["one",0,null,0,1,2,4,"two"]
Це код, який потрібно додати для IE, але фільтр та функціональне програмування варто imo.
//This prototype is provided by the Mozilla foundation and
//is distributed under the MIT license.
//http://www.ibiblio.org/pub/Linux/LICENSES/mit.license
if (!Array.prototype.filter)
{
Array.prototype.filter = function(fun /*, thisp*/)
{
var len = this.length;
if (typeof fun != "function")
throw new TypeError();
var res = new Array();
var thisp = arguments[1];
for (var i = 0; i < len; i++)
{
if (i in this)
{
var val = this[i]; // in case fun mutates this
if (fun.call(thisp, val, i, this))
res.push(val);
}
}
return res;
};
}
let newArr = arr.filter(e => e);
Можливо, вам буде простіше перевести цикл на масив і створити новий масив з елементів, які ви хочете зберегти з масиву, ніж намагаючись циклічно і з’єднувати, як було запропоновано, оскільки змінюєте довжину масиву під час його циклу може ввести проблеми.
Ви можете зробити щось подібне:
function removeFalsyElementsFromArray(someArray) {
var newArray = [];
for(var index = 0; index < someArray.length; index++) {
if(someArray[index]) {
newArray.push(someArray[index]);
}
}
return newArray;
}
Насправді тут є більш загальне рішення:
function removeElementsFromArray(someArray, filter) {
var newArray = [];
for(var index = 0; index < someArray.length; index++) {
if(filter(someArray[index]) == false) {
newArray.push(someArray[index]);
}
}
return newArray;
}
// then provide one or more filter functions that will
// filter out the elements based on some condition:
function isNullOrUndefined(item) {
return (item == null || typeof(item) == "undefined");
}
// then call the function like this:
var myArray = [1,2,,3,,3,,,,,,4,,4,,5,,6,,,,];
var results = removeElementsFromArray(myArray, isNullOrUndefined);
// results == [1,2,3,3,4,4,5,6]
Ви отримуєте ідею - тоді ви можете мати інші типи функцій фільтра. Напевно, більше, ніж потрібно, але я відчував себе щедрим ...;)
Слід використовувати фільтр, щоб отримати масив без порожніх елементів. Приклад на ES6
const array = [1, 32, 2, undefined, 3];
const newArray = array.filter(arr => arr);
Я просто додати свій голос до вищесказаного «заклик ES5 - х Array..filter()
з глобальним конструктора» гольф-хака, але я пропоную використовувати Object
замість String
, Boolean
або , Number
як було запропоновано вище.
Зокрема, ES5 filter()
вже не спрацьовує для undefined
елементів масиву; тому функція, яка універсально повертається true
, яка повертає всіfilter()
звернення елементів , обов'язково повертає лише неелементи undefined
:
> [1,,5,6,772,5,24,5,'abc',function(){},1,5,,3].filter(function(){return true})
[1, 5, 6, 772, 5, 24, 5, 'abc', function (){}, 1, 5, 3]
Однак виписувати ...(function(){return true;})
довше, ніж писати ...(Object)
; і повернене значення Object
конструктора буде, за будь-яких обставин , якимсь об’єктом. На відміну від конструкторів примітивного боксу, запропонованих вище, жодна можлива цінність об'єкта не є фальсією, і, таким чином, в булевій обстановці, Object
це короткий хід function(){return true}
.
> [1,,5,6,772,5,24,5,'abc',function(){},1,5,,3].filter(Object)
[1, 5, 6, 772, 5, 24, 5, 'abc', function (){}, 1, 5, 3]
someArray.filter(String);
фактично еквівалентний someArray.filter(function(x){ return String(x); });
. Якщо ви хочете видалити всі фальшиві значення, someArray.filter(Boolean);
працює для видалення 0, -0, NaN, false, '', null та undefined.
Object
конструктора на відміну від return true
методу. @robocat ОП попросив видалити порожні елементи, а не нулі.
Під час використання найвищої відповіді, зазначеної вище, у першому прикладі я отримував окремі символи довжиною рядків більше 1. Нижче моє рішення цієї проблеми.
var stringObject = ["", "some string yay", "", "", "Other string yay"];
stringObject = stringObject.filter(function(n){ return n.length > 0});
Замість того, щоб не повертатися, якщо не визначено, ми повертаємось, якщо довжина більше 0. Надіюсь, що хтось там допоможе.
Повертається
["some string yay", "Other string yay"]
["", "some string yay", "", "", 123, "Other string yay"].filter(function(n){ return n.length > 0}) //gives your same result removing 123
цю функцію. .. за іронією імені String залишає числа, але дасть такий же результат у вашому заданому масиві.
var data = [null, 1,2,3];
var r = data.filter(function(i){ return i != null; })
console.log(r)
[1,2,3]
Що на рахунок того:
js> [1,2,,3,,3,,,0,,,4,,4,,5,,6,,,,].filter(String).join(',')
1,2,3,3,0,4,4,5,6
join() === join(',')
:)
Це працює, я перевірив його в AppJet (ви можете скопіювати і вставити код на його IDE і натиснути «перезавантажити», щоб побачити його роботу, не потрібно створювати обліковий запис)
/* appjet:version 0.1 */
function Joes_remove(someArray) {
var newArray = [];
var element;
for( element in someArray){
if(someArray[element]!=undefined ) {
newArray.push(someArray[element]);
}
}
return newArray;
}
var myArray2 = [1,2,,3,,3,,,0,,,4,,4,,5,,6,,,,];
print("Original array:", myArray2);
print("Clenased array:", Joes_remove(myArray2) );
/*
Returns: [1,2,3,3,0,4,4,5,6]
*/
for ... in
це насправді викликає пропуск відсутніх елементів. Тест undefined
служить лише для видалення реальних елементів, явно встановлених на це значення.
Інший спосіб зробити це - скористатися властивістю довжини масиву: запакуйте ненульові елементи на "ліворуч" масиву, а потім зменшіть довжину. Це місцевий алгоритм - він не виділяє пам'ять, занадто поганий для сміттєзбірника, і він має дуже гарну найкращу / середню / гіршу поведінку.
Це рішення, порівняно з іншими тут, у 2–50 разів швидше на Chrome і в 5–50 разів швидше на Firefox, як ви могли бачити тут: http://jsperf.com/remove-null-items-from-array
Код нижче додає до масиву нечисленний метод 'deleteNull', який повертає 'це' для ланцюжка ромашок:
var removeNull = function() {
var nullCount = 0 ;
var length = this.length ;
for (var i=0, len=this.length; i<len; i++) { if (!this[i]) {nullCount++} }
// no item is null
if (!nullCount) { return this}
// all items are null
if (nullCount == length) { this.length = 0; return this }
// mix of null // non-null
var idest=0, isrc=length-1;
length -= nullCount ;
while (true) {
// find a non null (source) slot on the right
while (!this[isrc]) { isrc--; nullCount--; }
if (!nullCount) { break } // break if found all null
// find one null slot on the left (destination)
while ( this[idest]) { idest++ }
// perform copy
this[idest]=this[isrc];
if (!(--nullCount)) {break}
idest++; isrc --;
}
this.length=length;
return this;
};
Object.defineProperty(Array.prototype, 'removeNull',
{ value : removeNull, writable : true, configurable : true } ) ;
arr.filter(e => e)
.
"Неправильне використання" циклу for ... in (object-member). => У тілі циклу відображаються лише значення truthy.
// --- Example ----------
var field = [];
field[0] = 'One';
field[1] = 1;
field[3] = true;
field[5] = 43.68;
field[7] = 'theLastElement';
// --- Example ----------
var originalLength;
// Store the length of the array.
originalLength = field.length;
for (var i in field) {
// Attach the truthy values upon the end of the array.
field.push(field[i]);
}
// Delete the original range within the array so that
// only the new elements are preserved.
field.splice(0, originalLength);
for ... in
- це те, що вилучає невизначені ключі з масиву, але ви насправді тут не маєте коду, щоб інакше прийняти лише "truthy" значення
Це може допомогти вам: https://lodash.com/docs/4.17.4#remove
var details = [
{
reference: 'ref-1',
description: 'desc-1',
price: 1
}, {
reference: '',
description: '',
price: ''
}, {
reference: 'ref-2',
description: 'desc-2',
price: 200
}, {
reference: 'ref-3',
description: 'desc-3',
price: 3
}, {
reference: '',
description: '',
price: ''
}
];
scope.removeEmptyDetails(details);
expect(details.length).toEqual(3);
scope.removeEmptyDetails = function(details){
_.remove(details, function(detail){
return (_.isEmpty(detail.reference) && _.isEmpty(detail.description) && _.isEmpty(detail.price));
});
};
var data= {
myAction: function(array){
return array.filter(function(el){
return (el !== (undefined || null || ''));
}).join(" ");
}
};
var string = data.myAction(["I", "am","", "working", "", "on","", "nodejs", "" ]);
console.log(string);
Вихід:
Я працюю над nodejs
Він видалить порожній елемент з масиву та відобразить інший елемент.
Якщо масив містить порожні об'єкти, масиви та рядки поряд з іншими порожніми елементами, ми можемо їх видалити за допомогою:
const arr = [ [], ['not', 'empty'], {}, { key: 'value' }, 0, 1, null, 2, "", "here", " ", 3, undefined, 3, , , , , , 4, , 4, , 5, , 6, , , ]
let filtered = JSON.stringify(
arr.filter((obj) => {
return ![null, undefined, ''].includes(obj)
}).filter((el) => {
return typeof el != "object" || Object.keys(el).length > 0
})
)
console.log(JSON.parse(filtered))
З ES6:
const arr = [0, 1, null, 2, "", 3, undefined, 3, , , , , , 4, , 4, , 5, , 6, , , ,]
let filtered = arr.filter((obj) => { return ![null, undefined].includes(obj) })
console.log(filtered)
З простим Javascript ->
var arr = [0, 1, null, 2, "", 3, undefined, 3, , , , , , 4, , 4, , 5, , 6, , , ,]
var filtered = arr.filter(function (obj) { return ![null, undefined].includes(obj) })
console.log(filtered)
Фільтрація недійсних записів із регулярним виразом
array = array.filter(/\w/);
filter + regexp
Найкращий спосіб видалення порожніх елементів - це використання Array.prototype.filter()
, як уже говорилося в інших відповідях.
На жаль, Array.prototype.filter()
IE <9 не підтримується. Якщо вам все-таки потрібно підтримувати IE8 або навіть більш стару версію IE, ви можете скористатись такою полізаправкою, щоб додати підтримку Array.prototype.filter()
в цих браузерах:
if (!Array.prototype.filter) {
Array.prototype.filter = function(fun/*, thisArg*/) {
'use strict';
if (this === void 0 || this === null) {
throw new TypeError();
}
var t = Object(this);
var len = t.length >>> 0;
if (typeof fun !== 'function') {
throw new TypeError();
}
var res = [];
var thisArg = arguments.length >= 2 ? arguments[1] : void 0;
for (var i = 0; i < len; i++) {
if (i in t) {
var val = t[i];
if (fun.call(thisArg, val, i, t)) {
res.push(val);
}
}
}
return res;
};
}
var a = [,,]
таvar a = [undefined, undefined]
. Перший справді порожній, але останній насправді має два ключі, але зіundefined
значеннями.