Как удалить пустые элементы из массива в JavaScript?
Есть ли простой способ или мне нужно пропустить его и удалить вручную?



![Безумие обратных вызовов в javascript [JS]](https://i.imgur.com/WsjO6zJb.png)


Попробуй это. Передайте ему свой массив, и он вернется с удаленными пустыми элементами. * Обновлено для устранения ошибки, указанной Джейсоном.
function removeEmptyElem(ary) {
for (var i = ary.length - 1; i >= 0; i--) {
if (ary[i] == undefined) {
ary.splice(i, 1);
}
}
return ary;
}
НЕ используйте эту функцию, она не работает по очевидным причинам: попробуйте ее на этом массиве: var myArray = [1,2,, 3,, 3 ,,,,,, 4,, 4,, 5,, 6 ,, ,,];
Ах да, это несколько глючит. Если вы это исправите, я приму ваш ответ.
Это было обновлено и больше не должно вызывать ту же ошибку
Итерация начинается с i = ary.length, что неверно. Это должно быть i = ary.length-1
Он все еще глючит. он начинается с длины и проверяет массив [i], который в первом случае всегда будет неопределенным.
Возможно, вам будет проще перебрать ваш массив и создать новый массив из элементов, которые вы хотите сохранить в массиве, чем пытаться зацикливать и сращивать, как было предложено, поскольку изменение длины массива во время зацикливания может вызвать проблемы.
Вы можете сделать что-то вроде этого:
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]
Вы уловили идею - тогда у вас могут быть другие типы функций фильтрации. Наверное, больше, чем нужно, но я чувствовал себя щедрым ...;)
Обновлено: На этот вопрос был дан ответ почти девять лет назад, когда в 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.info(filtered);Это будет зависеть от того, что вы считаете «пустым», например, если вы имели дело со строками, указанная выше функция не удаляла бы элементы, являющиеся пустой строкой.
Один типичный шаблон, который я часто вижу, - это удаление элементов фальшивка, которые включают пустую строку "", 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.info(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,,,,]);
ВНИМАНИЕ: второй вариант удалит любые элементы из массива, считающегося «ложным», то есть значения false, 0, null и undefined. В этом массиве вообще ничего не останется: [null ,,, 0,, 0,0,0, false, null, 0], хотя мне могут понадобиться элементы со значениями 0, как в этом массиве: [ 1,0,1,0,0,1]
Да, второй метод, но первый вы передаете значение элементов, которые хотите удалить [null ,,, 0,, 0,0,0, false, null, 0] .clean (null) == [0 , 0,0,0, false, 0]
Я это понимаю - поэтому я говорил только о втором варианте. Что касается первого, то он настолько узок, что я не решился бы сделать его частью прототипа массива. См. Ответ Альнитака на этой странице, чтобы узнать что-то более идеальное. У вас, очевидно, есть возможность объединения в цепочку.
Ваше первое решение действительно хорошо, если у вас нет доступа к методу «фильтра». В противном случае я считаю, что ответ Альнитака лучше.
А у чего лучшая производительность? 1) или 2) подход? (или что-то вроде jQuery.grep () / Array.filter)
@AlfaTek - во всех, кроме новейших браузеров, №2 будет иметь лучшую производительность, потому что массивы в JS на самом деле не являются массивами. Вызов splice стоит В самом деле дорого в старых браузерах, потому что им приходится перенумеровать все ключи массива, чтобы закрыть пробел.
Мне нравится, как много из этих лучших ответов являются собственными расширениями, в то время как так много людей проповедуют, как это зло
Кроме того, вы можете написать свой цикл немного более производительным, избегая подсчета элементов массива в каждом цикле, например: for (var i = 0, j = actual.length; i <j; i ++)
@neonski ваше предложение не сработало для меня. Я пробовал results ['data'] = results ['data']. Slice (0); и результаты ['data'] по-прежнему содержат нулевые значения
Не могу поверить, сколько голосов набирают этот и второй ответ. Ни один из них не ответил на заданный вопрос.
ВНИМАНИЕ: первый метод может привести к сбою for (i in array). Чтобы предотвратить это, вы должны поместить if (array.hasOwnProperty(i)) { внутрь петли.
@ Дэвид, нет, в современном коде вы должны безопасно расширить Array.prototype с помощью Object.defineProperty, чтобы сделать новую функцию неперечислимое имущество, а затем избежать снижения производительности, вызванного помещением .hasOwnProperty в каждый цикл.
Голосуйте против, потому что он устарел. в настоящее время вы можете сделать это с помощью одного лайнера. const filteredArray = unfilteredArray.filter(item => *condition to keep item in array*)
Еще один короткий и красивый способ использования ECMA 5 - это [1, 2,,, 3,,,,,,,,, 4,, 4,,, 5,,, 6,,,,,].filter( e => e !== ('' || null || undefined)).
@Miquel, ты прав, я обновил ответ, прошло уже почти 10 лет!
массив [,'d','x'] с return el != null возвращает ,d,x, а если я использовал return el, я получаю правильный результат d,x, почему это ??
«Вы можете перейти к методу фильтра, функции логического конструктора ...», это правильно? Похоже, что Boolean используется как функция. Если я понимаю «функцию логического конструктора», то он должен создавать объект. Но 'typeof Boolean' возвращает 'function', а 'Boolean.constructor === Boolean' возвращает false. У этого кода есть некоторые вводящие в заблуждение аспекты - он использует поведение фильтра для пропуска - «обратный вызов вызывается только для индексов массива, которым присвоены значения». filter (Boolean), filter (Number) и filter (eval) избавляются от ложных значений и неназначенных (пустых) индексов.
Если у вас Javascript 1.6 или новее, вы можете использовать Array.filter, используя тривиальную функцию обратного вызова return true, например:
arr = arr.filter(function() { return true; });
поскольку .filter автоматически пропускает отсутствующие элементы в исходном массиве.
На указанной выше странице MDN также есть хорошая версия filter с проверкой ошибок, которую можно использовать в интерпретаторах JavaScript, которые не поддерживают официальную версию.
Обратите внимание, что это не удалит ни записи null, ни записи с явным значением undefined, но OP специально запросил «отсутствующие» записи.
Ты прав! Это может быть так просто (и работает!): Test3 = [1,2,, 3,, 3 ,,,, 7 ,,, 7 ,,, 0 ,,, 4,, 4,, 5 ,, 6,, undefined ,, null ,,]; printp ("Использование встроенной фильтрации массива:", test3.filter (function (value) {return (value == undefined)? 0: 1;}));
Да, это работает, но не во всех браузерах есть JavaScript 1.6, так что это только так.
+1 Как сказал Альнитак, у них есть код, который можно использовать в случае отсутствия js 1.6.
Да не пойдет. Похоже, это правда, пока он не неопределенный.
@katsh Я пояснил - код выше делает работает для удаления записей, для которых вообще нет значения, что (как я впоследствии узнал) семантически отличается от случая ключа, который существует, но имеет undefined в качестве заданного значения .
Чтобы удалить неопределенные или пустые записи, просто сделайте небольшую модификацию ... arr = arr.filter (function (v) {return v;});
@AlanCN, вы полностью упустили мою точку зрения. OP попросил удалить записи отсутствующий, в то время как большая часть ответов здесь (ошибочно) удаляет все «ложные» записи.
Это работает, я тестировал его в 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 служит только для удаления реальных элементов, для которых явно установлено это значение.
@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;
};
}
Это должен быть принятый ответ, поскольку он работает из коробки. Огромное спасибо.
@Tony нет, не должно, потому что элемент с пустой строкой в нем не то же самое, что «пустой элемент», последний и есть то, о чем просил OP.
Фильтрация недопустимых записей с помощью регулярного выражения
array = array.filter(/\w/);
filter + regexp
Это работает? показывает ошибку TypeError: [объект RegExp] не является функцией
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, ()=>{}]
Другие ответы не сработали для меня, потому что у меня был массив массивов. Это отлично работает ты +1.
Самая ранняя поддержка фильтра в IE - это стандартный режим IE9.
для чистого javascript это должно быть arr = arr.filter(function(n){return n; });
@yincrash - как я писал в своем первом комментарии
Данный ответ не работает. Вам необходимо вернуть элемент, как отмечает @ilumin. Например. [1,null,undefined,3,].filter(function(){;return true}) => [1, null, undefined, 3]
@broofa - работает. просто попробовал на IE, FF и CHROME. из W3C: filter calls a provided callback function once for each element in an array, and constructs a new array of all the values for which callback returns a true value.. и 'undefined', кстати, не пустое значение, так как null.
@vsync - это вопрос семантики, он зависит от того, что подразумевается под «пустым». Очевидно, он должен включать случаи, когда (key in array) == false, который фильтрует ваше решение. Но я почти уверен, что большинство людей также ожидают, что это будет включать и случай, когда (key in array) && (array[key] === undefined), что ваше решение не обрабатывает.
@broofa - ну, вы правы, и вы ошибаетесь, потому что я ответил на вопрос OP именно так, как ему было нужно, но это правда, что если вы хотите обнаружить 'undefined' (которое НЕ считается пустым значением), чем вы нужно изменить функцию фильтра
foo.join("").split("") работает только в том случае, если строки состоят из одиночных символов.
В вашем чистом коде JavaScript есть ошибка. Если в массиве есть значение с «0», значение будет отфильтровано, поскольку «0» является ложным. Вам нужно: arr.filter (function (n) {return (n! == undefined && n! == null);});
@JohnKurlak - ты прав, я исправил, но не так, как ты сказал.
jQuery должен иметь для этого встроенный метод. Или даже ES6!
ES6 может сделать это даже проще arr.filter(e=>e), и это можно связать с помощью map, reduce и т. д.
@Sheepy - круто, но для того, чтобы ES6 стал стандартом, потребуется целая вечность
@vsync Forever может появиться быстрее, чем вы думаете, потому что браузеры согласились отправлять сомнительные вещи в ES7. В техническом превью IE есть большинство ES6, а производственный Firefox уже может развлечься этим кодом.
да, вот что говорили про ES5, я помню тот день. и тем не менее, вряд ли кто-то использует ES5 ... к тому времени, когда выйдет ES7, люди будут жить на Марсе
@vsync, как упоминал @JohnKurlak, arr = arr.filter(Number) по-прежнему ошибочен, и вы должны удалить его из ответа
Как указали несколько человек, arr.filter(n => n) и его эквивалент в es5 удаляют ложные значения, что может быть нежелательно. Однако filter, как и другие методы массива, в любом случае выполняет итерацию только по определенным значениям. Таким образом, filter(n => true) - хороший чистый способ сжать разреженный массив.
Это должен быть принятый ответ. Аккуратное решение. Спасибо.
@ayushi этого не должно - это сбивает с толку исходный вопрос, в основном удаляя записи фальшивый, а не записи отсутствующий.
@Alnitak - я ничего не перепутал, я просто расширил исходный вопрос, потому что более вероятно, что люди, которые приходят сюда из Google, будут заинтересованы как в удалении пустых элементов, так и в предоставлении им решений по удалению других типов элементов, которые могут быть рассмотрены «пустой» для них в некоторых ситуациях.
$.grep(arr,function(n){ return n == 0 || n }); сохранит значение 0 в массиве :)
@DavChana - Ваш комментарий не имеет отношения к этому обсуждению. вы можете использовать приведенный выше код ответа, как хотите, вы можете изменить его, если вы предпочитаете !== вместо != ...
Лучше typeof n !== 'undefined' вместо n != undefined
@cnexans - У вас есть сценарий, подтверждающий это требование?
n != undefined может иметь две проблемы: 1. С переменными, которые еще не определены, будет выдана ошибка 2. Неопределенное может быть повторно объявлено (не в глобальной области), то есть function example() { var undefined = 1; }. Использование typeof n != 'undefined' - это способ всегда предотвратить эти (ужасные, но возможные) случаи.
@cnexans - Спасибо, но с уважением не согласен. Это крайние случаи насмешек, с которыми я никогда не сталкивался за все годы написания кода на javascript. У тебя? Если вы так глубоко погрузитесь в размышления о любом абсурдном крайнем случае, не будет конца. вот почему разработчики соблюдают правила и не создают переменные с именем undefined. иначе код накажет их ошибками, которых они вполне заслуживают.
this => // Стиль ES6 (Firefox FTW) arr.filter (n => true) // [1, 2, 3, 3, null, 0, undefined, 4, 4, 5, 6] !!
Что касается $ .grep, есть ли способ регистрировать / фиксировать все удаленные значения и их идентификаторы в неисправном / немодифицированном массиве? Я думаю, эта информация может быть полезна для синхронизации с другими массивами, которые могут быть связаны с массивом, очищенным от пустых и ложных значений.
delete temp; - Это не влияет на JavaScript, поскольку это может быть выполнено только для свойств объекта - попытка доступа к temp после этой строки приведет к тому же результату, как если бы вы изначально не выполняли delete temp;.
Что об этом:
js> [1,2,,3,,3,,,0,,,4,,4,,5,,6,,,,].filter(String).join(',')
1,2,3,3,0,4,4,5,6
Чистый способ сделать это.
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; это в основном удаляет все ложные значения.
Если вам нужно удалить ВСЕ пустые значения ("", 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}
@Koen Обратите внимание, что !!e будет включать NaN (в отличие от 0), тогда как e не будет (например, 0).
Фактически не отвечает на заданный вопрос.
@Alnitak: все зависит от того, как вы определяете «пустой». Я обновил свой ответ на основе вашего комментария. Спасибо!
Красиво и элегантно. +1
ИЛИ используйте var myarr=[1, 2,, 3,, 3,undefined,,"",,0, 4,, 4,, 5,, 6,,,,].filter(Boolean);, чтобы удалить undefined, "" и 0
Код ur иногда возвращает массив, который не определен как часть массива. но спасибо это помогло мне
Если я знаю, что использование библиотеки является вариантом, в underscore.js есть функция под названием compact () http://documentcloud.github.com/underscore/, а также несколько других полезных функций, связанных с массивами и коллекциями.
Вот выдержка из их документации:
_.compact(array)
Returns a copy of the array with all falsy values removed. In JavaScript, false, null, 0, "", undefined and NaN are all falsy.
_.compact([0, 1, false, 2, '', 3]);
=> [1, 2, 3]
Он также удаляет непустые элементы, определенные элементы, такие как 0.
Мне нужно было выполнить ту же задачу, и я наткнулся на эту тему. В итоге я использовал массив «join» для создания строки с использованием разделителя «_», а затем выполнил небольшое регулярное выражение, чтобы: -
1. replace "__" or more with just one "_",
2. replace preceding "_" with nothing "" and similarly
3. replace and ending "_" with nothing ""
... затем с помощью "split" массива для создания очищенного массива: -
var myArr = new Array("","","a","b","","c","","","","","","","","","e","");
var myStr = "";
myStr = myArr.join("_");
myStr = myStr.replace(new RegExp(/__*/g),"_");
myStr = myStr.replace(new RegExp(/^_/i),"");
myStr = myStr.replace(new RegExp(/_$/i),"");
myArr = myStr.split("_");
alert("myArr = " + myArr.join(","));
... или в 1 строке кода: -
var myArr = new Array("","","a","b","","c","","","","","","","","","e","");
myArr = myArr.join("_").replace(new RegExp(/__*/g),"_").replace(new RegExp(/^_/i),"").replace(new RegExp(/_$/i),"").split("_");
alert("myArr = " + myArr.join(","));
... или, расширяя объект Array: -
Array.prototype.clean = function() {
return this.join("_").replace(new RegExp(/__*/g),"_").replace(new RegExp(/^_/i),"").replace(new RegExp(/_$/i),"").split("_");
};
var myArr = new Array("","","a","b","","c","","","","","","","","","e","");
alert("myArr = " + myArr.clean().join(","));
Для строковых типов это работает, но может показаться «интересным» в массиве смешанного типа.
Я просто добавляю свой голос к вышеприведенному «вызову ES5's Array..filter() с глобальным конструктором», но я предлагаю использовать Object вместо String, Boolean или Number, как было предложено выше.
В частности, filter() ES5 уже не запускает элементы 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]
ВНИМАНИЕ: filter (String) и filter (Object) не отфильтровывают null или числа. Поскольку конструктор также является функцией, вы можете передать String для фильтрации, то есть someArray.filter(String); фактически эквивалентен someArray.filter(function(x){ return String(x); });. Если вы хотите удалить все ложные значения, someArray.filter(Boolean); удаляет 0, -0, NaN, false, '', null и undefined.
Хороший ответ, хотя меня интересуют накладные расходы на производительность при вызове конструктора Object в отличие от метода return true. @robocat OP попросил удалить пустые элементы, а не нули.
Я предпочитаю самое короткое и ясное решение, за исключением узких петель. Полагаю, личные предпочтения. знак равно
С подчеркиванием / 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 для без.
Проблема с #compact заключается в том, что он удаляет любые ложные значения. Поэтому, если ваш массив содержит 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, если значение истинно / ложно.
Вы не лечение Boolean как функция; это является функция. (Совершенно нормальная функция, за исключением того, что она реализована изначально.) Кому-то нужно провести небольшое исследование объектной модели JavaScript. ;)
@ELLIOTTCABLE Я просто оставлю это здесь, (true).constructor === Boolean. А затем скажите мне, можем ли мы сделать это с помощью других встроенных модулей JS. ;)) (конечно исключены другие 5 встроенных конструкторов. (String, Array, Object, Function, Number))
Понятия не имею, что ты говоришь, @null.
@ dev-null все конструкторы JS являются функциями - важно, позволяют ли они также вызывать себя без new или нет. Boolean делает, как и другие стандартные типы, но обычно функции DOM браузера этого не делают.
Не получится и то, и другое, если в массиве есть значение 0
Другой способ сделать это - воспользоваться свойством массива length: упаковать ненулевые элементы «слева» от массива, а затем уменьшить длину. Это встроенный алгоритм, который не выделяет память, что плохо для сборщика мусора, и имеет очень хорошее поведение в лучшем / среднем / худшем случае.
Это решение, по сравнению с другими здесь, от 2 до 50 раз быстрее в Chrome и в 5-50 раз быстрее в Firefox, как вы можете видеть здесь: 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 } ) ;
Хороший ответ, хотя было бы неплохо увидеть несколько тестовых примеров, чтобы продемонстрировать его в действии!
Этот ответ очень увлекателен, но отчасти напоминает мне взгляд на компьютер 1945 года, когда у меня был смартфон: arr.filter(e => e).
@ agm1984 твой смартфон не умен
Это может зависеть от вашего определения smart - например, глагола «вызывать острую жалящую боль». Это актуально из-за физической боли, если я использую свой телефон в качестве оружия из-за вашего комментария.
Мило очень мило Мы также можем заменить все значения массива следующим образом
Array.prototype.ReplaceAllValues = function(OldValue,newValue)
{
for( var i = 0; i < this.length; i++ )
{
if ( this[i] == OldValue )
{
this[i] = newValue;
}
}
};
foo = [0, 1, 2, "", , false, 3, "four", null]
foo.filter(function(e) {
return e === 0 ? '0' : e
})
возвращается
[0, 1, 2, 3, "four"]
При использовании ответа с наибольшим количеством голосов выше, в первом примере, я получал отдельные символы для строк длиной больше 1. Ниже представлено мое решение этой проблемы.
var stringObject = ["", "some string yay", "", "", "Other string yay"];
stringObject = stringObject.filter(function(n){ return n.length > 0});
Вместо того, чтобы не возвращаться, если undefined, мы возвращаемся, если длина больше 0. Надеюсь, что это поможет кому-то там.
Возврат
["some string yay", "Other string yay"]
+1, поскольку это очень практично и именно то, что мне обычно нужно для работы со строковыми массивами, но имейте в виду, что это удаляет числа (если они не в строковой форме), поскольку у них нет .lenghth, поэтому ["", "some string yay", "", "", 123, "Other string yay"].filter(function(n){ return n.length > 0}) //gives your same result removing 123 Замена этой функции ... со String, по иронии судьбы, оставляет числа, но даст тот же результат в вашем заданном массиве.
Это еще один способ:
var arr = ["a", "b", undefined, undefined, "e", undefined, "g", undefined, "i", "", "k"]
var cleanArr = arr.join('.').split(/\.+/);
Это действительно плохая идея .. Что, если одно из значений - «a.string.with.dots»? Он будет разбит на части при создании нового массива ...
Вам решать, какой символ вы выберете для соединения / разделения, вам не нужно использовать точку, если у вас есть a.string.with.dots
@BogdanGersak Что делать, если во время разработки вы не можете гарантировать, будет ли строка содержать или не содержать какой-либо конкретный символ?
Поскольку никто больше не упоминал об этом, и большинство людей включили в свой проект подчеркивание, вы также можете использовать _.without(array, *values);.
_.without(["text", "string", null, null, null, "text"], null)
// => ["text", "string", "text"]
Вот пример использования вариативного поведения и выражения жирной стрелки ES2015:
Array.prototype.clean = function() {
var args = [].slice.call(arguments);
return this.filter(item => args.indexOf(item) === -1);
};
// Usage
var arr = ["", undefined, 3, "yes", undefined, undefined, ""];
arr.clean(undefined); // ["", 3, "yes", ""];
arr.clean(undefined, ""); // [3, "yes"];
Как насчет этого (ES6): удалить значение Falsy из массива.
var arr = [0,1,2,"test","false",false,true,null,3,4,undefined,5,"end"];
arr.filter((v) => (!!(v)==true));
//output:
//[1, 2, "test", "false", true, 3, 4, 5, "end"]
Лучший способ удалить пустые элементы - использовать 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;
};
}
«Неправильное использование» цикла for ... in (объект-член). => В теле цикла появляются только истинные значения.
// --- 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 - это то, что удаляет неопределенные ключи из массива, но на самом деле у вас здесь нет кода, чтобы в противном случае принимать только «правдивые» значения.
Как насчет того, чтобы сделать это таким образом
// Removes all falsy values
arr = arr.filter(function(array_val) { // creates an anonymous filter func
var x = Boolean(array_val); // checks if val is null
return x == true; // returns val to array if not null
});
Пожалуйста, объясните это немного, чтобы помочь другим пользователям.
Если кто-то хочет очистить весь массив или объект, это может помочь.
var qwerty = {
test1: null,
test2: 'somestring',
test3: 3,
test4: {},
test5: {
foo: "bar"
},
test6: "",
test7: undefined,
test8: " ",
test9: true,
test10: [],
test11: ["77","88"],
test12: {
foo: "foo",
bar: {
foo: "q",
bar: {
foo:4,
bar:{}
}
},
bob: {}
}
}
var asdfg = [,,"", " ", "yyyy", 78, null, undefined,true, {}, {x:6}, [], [2,3,5]];
function clean_data(obj) {
for (var key in obj) {
// Delete null, undefined, "", " "
if (obj[key] === null || obj[key] === undefined || obj[key] === "" || obj[key] === " ") {
delete obj[key];
}
// Delete empty object
// Note : typeof Array is also object
if (typeof obj[key] === 'object' && Object.keys(obj[key]).length <= 0) {
delete obj[key];
}
// If non empty object call function again
if (typeof obj[key] === 'object'){
clean_data(obj[key]);
}
}
return obj;
}
var objData = clean_data(qwerty);
console.info(objData);
var arrayData = clean_data(asdfg);
console.info(arrayData);
Выход:
Удаляет все, что есть null, undefined, "", " ", empty object или empty array
jsfiddle здесь
Он удалит только пустые значения, а не ложные, что, на мой взгляд, более желательно.
Также есть возможность удалить нулевые значения.
Этот метод должен быть намного быстрее, чем сращивание.
function cleanArray(a, removeNull) {
var i, l, temp = [];
l = a.length;
if (removeNull) {
for (i = 0; i < l; i++) {
if (a[i] !== undefined && a[i] !== null) {
temp.push(a[i]);
}
}
} else {
for (i = 0; i < l; i++) {
if (a[i] !== undefined) {
temp.push(a[i]);
}
}
}
a.length = 0;
l = temp.length;
for (i = 0; i < l; i++) {
a[i] = temp[i];
}
temp.length = 0;
return a;
}
var myArray = [1, 2, , 3, , 3, , , 0, , null, false, , NaN, '', 4, , 4, , 5, , 6, , , , ];
cleanArray(myArray);
myArray;
Простой ES6
['a','b','',,,'w','b'].filter(v => v);
Это не работает: [1, 'two', null, undefined, , NaN, false, true, 0].filter(v => v).
var data = [null, 1,2,3];
var r = data.filter(function(i){ return i != null; })
console.info(r)
[1,2,3]
Это, очевидно, правильный способ сделать это, и он должен быть на вершине!
Это может вам помочь: 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 s = [ '1,201,karthikeyan,K201,HELPER,[email protected],8248606269,7/14/2017,45680,TN-KAR24,8,800,1000,200,300,Karthikeyan,11/24/2017,Karthikeyan,11/24/2017,AVAILABLE\r',
'' ]
var newArr = s.filter(function(entry) { return entry.trim() != ''; })
console.info(newArr); Вы должны использовать фильтр, чтобы получить массив без пустых элементов. Пример на ES6
const array = [1, 32, 2, undefined, 3];
const newArray = array.filter(arr => arr);
Для удаления дырок следует использовать
arr.filter(() => true)
arr.flat(0) // New in ES2019, check compatibility before using this
Для удаления hole, null и undefined:
arr.filter(x => x != null)
Для удаления дыр и ложных значений (null, undefined, 0, -0, 0n, NaN, "", false, document.all):
arr.filter(x => x)
arr = [, null, (void 0), 0, -0, 0n, NaN, false, '', 42];
console.info(arr.filter(() => true)); // [null, (void 0), 0, -0, 0n, NaN, false, '', 42]
console.info(arr.filter(x => x != null)); // [0, -0, 0n, NaN, false, "", 42]
console.info(arr.filter(x => x)); // [42]Это должно быть высоко в ответе. Можете ли вы расширить то, что вы подразумеваете под дырками / дырами ..?
@samayo - это незаполненные элементы массива, например [, ,].
Используя arr.filter(x => x), JS проверит, является ли x истинным или ложным, то есть if (x), поэтому новому списку будет присвоено только истинное значение.
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.info(string);
Выход:
I am working on nodejs
Он удалит пустой элемент из массива и отобразит другой элемент.
вывод: «Я работаю над nodejs». он удалит пустой элемент из массива и отобразит другой элемент.
Я улучшил ваш ответ. Пожалуйста, постарайтесь дать простой, понятный и читаемый ответ;)
let newArr = arr.filter(e => e);
Просто метод ES6 и более новых версий, предположим, что массив ниже:
const arr = [1,2,3,undefined,4,5,6,undefined,7,8,undefined,undefined,0,9];
Простой способ:
const clearArray = arr.filter( i => i );
это мое решение для чистых пустых полей.
Начать с объекта комиссии: получить только атрибут avail (с картой) фильтровать пустые поля (с фильтром) преобразовать результаты в целое число (с картой)
fees.map( ( e ) => e.avail ).filter( v => v!== '').map( i => parseInt( i ) );
Готовое решение:
function pack(arr) { // remove undefined values
let p = -1
for (let i = 0, len = arr.length; i < len; i++) {
if (arr[i] !== undefined) { if (p >= 0) { arr[p] = arr[i]; p++ } }
else if (p < 0) p = i
}
if (p >= 0) arr.length = p
return arr
}
let a = [1, 2, 3, undefined, undefined, 4, 5, undefined, null]
console.info(JSON.stringify(a))
pack(a)
console.info(JSON.stringify(a))
var a = [{a1: 1, children: [{a1: 2}, undefined, {a1: 3}]}, undefined, {a1: 5}, undefined, {a1: 6}]
function removeNilItemInArray(arr) {
if (!arr || !arr.length) return;
for (let i = 0; i < arr.length; i++) {
if (!arr[i]) {
arr.splice(i , 1);
continue;
}
removeNilItemInArray(arr[i].children);
}
}
var b = a;
removeNilItemInArray(a);
// Always keep this memory zone
console.info(b);
Если массив содержит пустые объекты, массивы и строки вместе с другими пустыми элементами, мы можем удалить их с помощью:
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.info(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.info(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.info(filtered)Привет, я просто хотел спросить, есть ли способ удалить нулевые элементы из 2D / вложенного массива в ES 6?
Привет @Mob_Abominator, это, безусловно, можно сделать, попробуйте ту же логику, обратившись к вложенному массиву.
Все пустые элементы можно удалить из массива, просто используя
array.filter(String);
Он возвращает все непустые элементы массива в javascript
К сожалению, он принимает null, а при использовании Boolean удаляет пустые строки.
@PaulWatson Да, к сожалению, он принимает null как строку, но может удалять пустые элементы из массива. Надеюсь ты понимаешь
Вы можете использовать фильтр с индексом и оператором in
let a = [1,,2,,,3];
let b = a.filter((x,i)=> i in a);
console.info({a,b});предполагая, что массив содержит номера индексов ...?
@Magne в стандартных массивах JS индексы - это числа. Объекты JS могут содержать другие ключи, кроме чисел. Массивы JS также являются объектами, и вы можете добавить к ним пару ключ-значение, например let a=[]; a.abc=1, но обычно этого не делает никто (это довольно экзотично, потому что вместо массивов вы можете просто использовать, например, объект {}). И когда вы используете массив таким экзотическим способом, стандартные методы массива JS, такие как map, filter и т. д., Будут игнорировать такие пары ключ-значение - мое решение, основанное на filter, и игнорировать его тоже. Совершенно очевидно, что OP спрашивает о стандартном массиве JS (потому что он не упоминает о таком экзотическом варианте использования)
да, на самом деле я не имел в виду это, но спасибо, что прояснили это тоже. Я просмотрел верхнюю часть developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/… и смутно полагаю, что оператор in вернул значение в массиве. Поэтому я подумал, что это сработает, только если значения в массиве будут такими же, как номера индексов, по которым нужно фильтровать. Но теперь я вижу, что in относится к свойствам (например, индексам), а не к значениям массива.
ТАК не позволил мне изменить свой голос. :( Если вы сделаете небольшую правку, то я могу изменить свой голос.
@Magne хорошо, я редактирую это сейчас
отлично, я проголосовал сейчас.
Было бы полезно, если бы в вашем вопросе было точно указано, что вы подразумеваете под «пустыми элементами», поскольку большинство ответов здесь интерпретируют это неправильно (ИМХО) как означающие «ложные» элементы. NB: есть разница между тем, что вы получаете для
var a = [,,]иvar a = [undefined, undefined]. Первый действительно пустой, но последний фактически имеет два ключа, но со значениямиundefined.