Как удалить пустые элементы из массива в JavaScript?
Есть ли простой способ, или мне нужно пройти через него и удалить их вручную?
Как удалить пустые элементы из массива в JavaScript?
Есть ли простой способ, или мне нужно пройти через него и удалить их вручную?
Ответы:
РЕДАКТИРОВАТЬ: На этот вопрос был дан ответ почти девять лет назад, когда не было много полезных встроенных методов в 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
метод, передающий обратный вызов, который возвращает true, например:
var sparseArray = [0, , , 1, , , , , 2, , , , 3],
cleanArray = sparseArray.filter(function () { return true });
console.log(cleanArray); // [ 0, 1, 2, 3 ]
Старый ответ: не делай этого!
Я использую этот метод, расширяя собственный прототип Array:
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, " "]
ОБНОВЛЕНИЕ (на основе комментария Алнитак)
В некоторых ситуациях вы можете захотеть сохранить «0» в массиве и удалить все остальное (null, undefined и «»), это один из способов:
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 / false.
(true).constructor === Boolean
. А затем скажите мне, можем ли мы сделать это с другими встроенными модулями в JS. ;)) (конечно, исключены остальные 5 встроенных конструкторов. (String, Array, Object, Function, Number))
Если у вас есть Javascript 1.6 или более поздней версии, вы можете использовать Array.filter
тривиальную return true
функцию обратного вызова, например:
arr = arr.filter(function() { return true; });
так как .filter
автоматически пропускает отсутствующие элементы в исходном массиве.
Страница MDN, ссылка на которую приведена выше, также содержит хорошую версию для проверки ошибок, filter
которую можно использовать в интерпретаторах JavaScript, которые не поддерживают официальную версию.
Обратите внимание, что это не удалит null
ни записи, ни записи с явным undefined
значением, но OP специально запросил «пропущенные» записи.
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)
Для удаления отверстия, нуля и неопределенного:
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, проверим, является ли x истинным или ложным, т. Е. 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
; это в основном удаляет все ложные значения.
С Подчеркиванием / Lodash:
Общий случай использования:
_.without(array, emptyVal, otherEmptyVal);
_.without([1, 2, 1, 0, 3, 1, 4], 0, 1);
С тарами:
_.without(['foo', 'bar', '', 'baz', '', '', 'foobar'], '');
--> ["foo", "bar", "baz", "foobar"]
Смотрите документацию по lodash без .
Если использование библиотеки является опцией, которую я знаю, в underscore.js есть функция compact () 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, но фильтрация и функциональное программирование стоят того же.
//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
служит только для удаления реальных элементов, для которых явно задано это значение.
Другой способ сделать это - воспользоваться преимуществом свойства length массива: упаковать ненулевые элементы в «левом» массиве, а затем уменьшить длину. Это алгоритм на месте - он не выделяет память, что очень плохо для сборщика мусора, и он работает очень хорошо в наилучшем / среднем / худшем случаях.
Это решение, по сравнению с другими, в Chrome работает в 2–50 раз быстрее, а в Firefox - в 5–50 раз, как вы можете видеть здесь: http://jsperf.com/remove-null-items-from-array
Приведенный ниже код добавляет неперечислимый метод 'removeNull' в массив, который возвращает 'this' для последовательного подключения:
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)
.
smart
такой как глагол, чтобы вызвать острую жгучую боль. Это актуально из-за физической боли, если я из-за вашего комментария пользуюсь телефоном.
«Неправильное использование» цикла for ... in (object-member). => В теле цикла отображаются только истинные значения.
// --- 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
- это то, что удаляет неопределенные ключи из массива, но у вас фактически нет здесь кода, чтобы в противном случае принимать только «истинные» значения
Это может помочь вам: 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, вы можете использовать следующий polyfill для добавления поддержки 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
значениями.