Usuń puste elementy z tablicy w JavaScript

1144

Jak usunąć puste elementy z tablicy w JavaScript?

Czy istnieje prosty sposób, czy muszę go zapętlić i usunąć ręcznie?

Tamas Czinege
źródło
14
Byłoby pomocne, gdyby twoje pytanie precyzowało dokładnie, co rozumiesz przez „puste elementy”, ponieważ większość odpowiedzi tutaj interpretuje to niepoprawnie (IMHO) jako elementy „falsey”. Uwaga: istnieje różnica między tym, za co dostajesz var a = [,,]a var a = [undefined, undefined]. Pierwsza jest naprawdę pusta, ale druga faktycznie ma dwa klucze, ale z undefinedwartościami.
Alnitak,

Odpowiedzi:

1064

EDYCJA: Odpowiedzi na to pytanie prawie dziewięć lat temu, kiedy nie było wielu przydatnych metod wbudowanych wArray.prototype .

Teraz z pewnością poleciłbym ci skorzystanie z filter metody.

Weź pod uwagę, że ta metoda zwróci ci nową tablicę z elementami spełniającymi podane przez ciebie kryteria funkcji zwrotnej.

Na przykład, jeśli chcesz usunąć nulllub undefinedwartości:

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);

Będzie to zależeć od tego, co uważasz za „puste”, na przykład, jeśli masz do czynienia z łańcuchami, powyższa funkcja nie usunie elementów, które są pustymi łańcuchami.

Jeden typowy wzór, który widzę często wykorzystywane jest do usunięcia elementów, które są falsy , które zawierają ciąg pusty "", 0, NaN, null, undefined, ifalse .

Możesz przejść do filtermetody, Booleanfunkcji konstruktora lub zwrócić ten sam element w funkcji kryteriów filtrowania, na przykład:

var filtered = array.filter(Boolean);

Lub

var filtered = array.filter(function(el) { return el; });

W obu przypadkach działa to, ponieważ filtermetoda w pierwszym przypadku wywołuje Booleankonstruktor jako funkcję, konwertując wartość, aw drugim przypadku filtermetoda wewnętrznie zamienia wartość zwrotną wywołania zwrotnego niejawnie na Boolean.

Jeśli pracujesz z rzadkimi tablicami i próbujesz pozbyć się „dziur”, możesz użyć filtermetody przekazującej wywołanie zwrotne zwracające wartość true, na przykład:

var sparseArray = [0, , , 1, , , , , 2, , , , 3],
    cleanArray = sparseArray.filter(function () { return true });

console.log(cleanArray); // [ 0, 1, 2, 3 ]

Stara odpowiedź: nie rób tego!

Używam tej metody, rozszerzając natywny prototyp 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);

Lub możesz po prostu wepchnąć istniejące elementy do innej tablicy:

// 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,,,,]);
CMS
źródło
110
OSTRZEŻENIE: Druga opcja usunie wszystkie elementy z tablicy uważanej za „fałsz”, tj. Wartości false, 0, null i undefined. Ta tablica kończy się niczym: [null ,,, 0, 0,0,0, false, null, 0] nawet jeśli mogę chcieć elementów o wartości 0, jak w tej tablicy: [ 1,0,1,0,0,1]
Jason Bunting
5
Zdaję sobie z tego sprawę - dlatego mówiłem tylko o drugiej opcji. Jeśli chodzi o pierwszy, ma on tak wąski zakres, że zawahałbym się, aby włączyć go do prototypu tablicy. Zobacz odpowiedź Alnitaka na tej stronie, aby znaleźć coś, co byłoby bardziej idealne. Oczywiście, twoje pozwala na tworzenie łańcuchów.
Jason Bunting
1
Twoje pierwsze rozwiązanie jest naprawdę miłe, jeśli nie masz dostępu do metody „filtrowania”. W przeciwnym razie uważam, że odpowiedź Alnitaka jest lepsza.
Joe Pineda,
2
@AlfaTek - na wszystkich oprócz najnowszych przeglądarek # 2 będzie miała najlepszą wydajność, ponieważ tablice w JS nie są tak naprawdę tablicami. splicePołączenie jest bardzo drogie w starszych przeglądarkach, ponieważ muszą zmienić numerację wszystkich kluczy tablicy, aby zamknąć lukę.
Alnitak,
1
@David nie, we współczesnym kodzie należy bezpiecznie rozszerzyć Array.prototypeza pomocą, Object.definePropertyaby nowa funkcja była właściwością niewymienną, a następnie uniknąć pogorszenia wydajności spowodowanego wstawieniem .hasOwnPropertykażdej pętli.
Alnitak
1381

Proste sposoby:

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]

lub - (tylko dla pojedynczych elementów tablicy typu „tekst”)

['','1','2',3,,'4',,undefined,,,'5'].join('').split(''); 
// output:  ["1","2","3","4","5"]

lub - Klasyczny sposób: prosta iteracja

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]


przez jQuery:

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]


AKTUALIZACJA - kolejny szybki i fajny sposób (za pomocą ES6):

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]

Usuń puste wartości

['foo', '',,,'',,null, ' ', 3, true, [], [1], {}, undefined, ()=>{}].filter(String)

// ["foo", null, " ", 3, true, [1], Object {}, undefined, ()=>{}]
vsync
źródło
34
najwcześniejsza obsługa IE dla filtra to tryb standardów IE9.
yincrash
14
dla czystego javascript powinien to byćarr = arr.filter(function(n){return n; });
ilumin
19
foo.join("").split("")wydaje się, że działa tylko wtedy, gdy ciągi znaków są pojedynczymi znakami
Atav32
8
Twój czysty kod JavaScript ma błąd. Jeśli tablica ma wartość „0”, wartość zostanie odfiltrowana, ponieważ „0” to fałsz. Co chcesz: arr.filter (function (n) {return (n! == undefined && n! == null);});
John Kurlak,
5
ES6 może to zrobić jeszcze prościej, arr.filter(e=>e)a to można powiązać za pomocą mapy, redukcji itp.
Sheepy
241

Jeśli chcesz usunąć WSZYSTKIE puste wartości („”, null, undefined i 0):

arr = arr.filter(function(e){return e}); 

Aby usunąć puste wartości i podziały wiersza:

arr = arr.filter(function(e){ return e.replace(/(\r\n|\n|\r)/gm,"")});

Przykład:

arr = ["hello",0,"",null,undefined,1,100," "]  
arr.filter(function(e){return e});

Powrót:

["hello", 1, 100, " "]

AKTUALIZACJA (na podstawie komentarza Alnitaka)

W niektórych sytuacjach możesz chcieć zachować „0” w tablicy i usunąć wszystko inne (null, undefined i „”), jest to jeden ze sposobów:

arr.filter(function(e){ return e === 0 || e });

Powrót:

["hello", 0, 1, 100, " "]
lepe
źródło
Tak, to miłe, ponieważ usuwa również „”.
Vladimirs
3
Funkcja testowa może być nieco bardziej wyraźna:function(e){return !!e}
Koen.
4
@Koen Należy pamiętać, że !!ebędzie zawierać NaN (w przeciwieństwie do 0) whereous enie (jak 0).
Owca
W rzeczywistości nie odpowiada na zadane pytanie.
Alnitak
2
LUB użycie var myarr=[1, 2,, 3,, 3,undefined,,"",,0, 4,, 4,, 5,, 6,,,,].filter(Boolean);usuwa niezdefiniowane „” i 0
Mark Schultheiss
134

Po prostu jedna wkładka:

[1, false, "", undefined, 2].filter(Boolean); // [1, 2]

lub używając underscorejs.org :

_.filter([1, false, "", undefined, 2], Boolean); // [1, 2]
// or even:
_.compact([1, false, "", undefined, 2]); // [1, 2]
andlrc
źródło
1
To jest naprawdę fajne - mam jednak nowe pytanie: wygląda na to, że używasz nazwy klasy jako wywołania funkcji - czy to rzutowanie tekstu? Nie widziałem tego wcześniej i nie jestem pewien, dlaczego rozumiem, dlaczego przekazywanie Booleandziała jako funkcja ...
Andrew
8
Jeśli potraktujesz Booleanjako funkcję, po prostu wróci truelub falsespadnie, wartość jest prawdziwie / fałszywa.
andlrc
8
Nie traktujesz Boolean jako funkcji; to jest funkcja. (Zupełnie normalna funkcja, z tym wyjątkiem, że jest implementowana natywnie). Ktoś musi przeprowadzić małe badanie modelu obiektowego JavaScript. ;)
ELLIOTTCABLE
@ELLIOTTCABLE Im po prostu zostawię to tutaj (true).constructor === Boolean. A potem powiedz mi, czy możemy to zrobić z innymi wbudowaniami w JS. ;)) (oczywiście wykluczono 5 innych wbudowanych konstruktorów. (String, Array, Object, Function, Number))
andlrc
1
Oba zawiodą, jeśli w tablicy jest wartość 0
Sai Ram
129

Jeśli masz Javascript w wersji 1.6 lub nowszej, możesz użyć Array.filtertrywialnej return truefunkcji zwrotnej, np .:

arr = arr.filter(function() { return true; });

ponieważ .filterautomatycznie pomija brakujące elementy w oryginalnej tablicy.

Strona MDN, do której prowadzi powyższy link, zawiera także niezłą wersję sprawdzającą błędy, filterktórej można używać w interpreterach JavaScript, które nie obsługują oficjalnej wersji.

Należy pamiętać, że nie spowoduje to usunięcia nullwpisów ani wpisów o wyraźnej undefinedwartości, ale OP wyraźnie zażądał „brakujących” wpisów.

Alnitak
źródło
Masz rację! Może to być tak proste (i działa!): Test3 = [1,2, 3,, 3 ,,,, 7 ,,, 7 ,,, 0 ,,, 4,, 4,, 5 ,, 6, niezdefiniowany ,, null ,,]; printp („Korzystanie z natywnego filtrowania tablicy:”, test3.filter (funkcja (wartość) {return (wartość == niezdefiniowana)? 0: 1;}));
Joe Pineda,
3
+1 Jak powiedział Alnitak, mają kod, którego można użyć w przypadku braku dostępnego js 1.6
Sameer Alibhai
3
@katsh mam wyjaśnić - powyższy kod ma pracę, aby usunąć wpisy, dla których nie istnieje żadna wartość w ogóle, który (mam później) dowiedziałem jest semantycznie różni się od przypadku kluczem, który istnieje, ale która ma undefinedjako danej wartości.
Alnitak,
4
Aby usunąć niezdefiniowane lub puste wpisy, po prostu dokonaj niewielkiej modyfikacji ... arr = arr.filter (function (v) {return v;});
Alan CN,
4
@AlanCN całkowicie przegapiłeś mój punkt. OP poprosił o usunięcie brakujących wpisów, podczas gdy większość odpowiedzi tutaj (niepoprawnie) usuwa wszelkie „falsey” wpisy.
Alnitak,
65

Do usuwania dziur należy użyć

arr.filter(() => true)
arr.flat(0) // Currently stage 3, check compatibility before using this

Do usuwania wartości dołków i fałszowania (null, undefined, 0, -0, NaN, "", false, document.all):

arr.filter(x => x)

Aby usunąć hole, null i, 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]

tsh
źródło
3
To powinno być wysoko w odpowiedzi. Czy możesz rozwinąć to, co rozumiesz przez dziury / dziury ...?
samayo
2
Otwory @samayo to niewypełnione elementy tablicy, tj.[, ,]
Jimmy Obonyo Abor
Za pomocą arr.filter(x => x)JS sprawdzi, czy x jest prawdą czy fałszem, tzn. if (x)Dlatego tylko nowa wartość prawdy zostanie przypisana do nowej listy.
KuanYu Chu
56

Czysty sposób na zrobienie tego.

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"]
Tomás Senart
źródło
5
Pustymi elementami są undefined; to w zasadzie usuwa wszystkie wartości fałszowania.
pimvdb
33

Prosty ES6

['a','b','',,,'w','b'].filter(v => v);
ML13
źródło
1
To nie działa: [1, 'two', null, undefined, , NaN, false, true, 0].filter(v => v).
zamek błyskawiczny
22

Z podkreśleniem / Lodash:

Ogólny przypadek użycia:

_.without(array, emptyVal, otherEmptyVal);
_.without([1, 2, 1, 0, 3, 1, 4], 0, 1);

Z pustkami:

_.without(['foo', 'bar', '', 'baz', '', '', 'foobar'], '');
--> ["foo", "bar", "baz", "foobar"]

Zobacz dokumentację lodash bez .

c4urself
źródło
Problem z #compact polega na tym, że usuwa on wszystkie wartości fałszowania. Więc jeśli tablica zawiera 0 wartości, zostaną one również usunięte.
Samuel Brandão
21

Tylko ES6i nowsze metody wersji, zakładamy, że tablica jest poniżej:

 const arr = [1,2,3,undefined,4,5,6,undefined,7,8,undefined,undefined,0,9];

Prosta droga:

 const clearArray = arr.filter( i => i );
AmerllicA
źródło
16

Jeśli korzystanie z biblioteki jest opcją, wiem, że underscore.js ma funkcję o nazwie compact () http://documentcloud.github.com/underscore/, ale ma także kilka innych przydatnych funkcji związanych z tablicami i kolekcjami.

Oto fragment ich dokumentacji:

_.compact (tablica)

Zwraca kopię tablicy z usuniętymi wszystkimi wartościami fałszowania. W JavaScript, false, null, 0, „”, undefined i NaN są fałszywe.

_.compact ([0, 1, false, 2, '', 3]);

=> [1, 2, 3]

Luis Perez
źródło
Usuwa również niepuste elementy zdefiniowane elementy, takie jak 0.
Timothy Gu
15

@Alnitak

Właściwie Array.filter działa we wszystkich przeglądarkach, jeśli dodasz dodatkowy kod. Patrz poniżej.

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"]  

Jest to kod, który musisz dodać do IE, ale warto też użyć filtru i programowania funkcjonalnego.

//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;
  };
}
Erik Johansson
źródło
To powinna być zaakceptowana odpowiedź, ponieważ działa ona od razu po wyjęciu z pudełka. Dziękuję bardzo.
Tony,
@ Tony nie, nie powinno, ponieważ element z pustym łańcuchem nie jest tym samym co „pusty element”, przy czym ten ostatni jest tym, o co prosi OP.
Alnitak
14

Ponieważ nikt inny o tym nie wspominał, a większość ludzi ma podkreślenie w swoim projekcie, możesz również użyć _.without(array, *values);.

_.without(["text", "string", null, null, null, "text"], null)
// => ["text", "string", "text"]
Josh Bedo
źródło
12

ES6:

let newArr = arr.filter(e => e);
Kanan Farzali
źródło
8

Może być łatwiej zapętlić tablicę i zbudować nową tablicę z elementów, które chcesz zachować z tablicy, niż próbować zapętlić i splicować zgodnie z sugestią, ponieważ modyfikacja długości tablicy podczas jej zapętlania może wprowadzać problemy.

Możesz zrobić coś takiego:

function removeFalsyElementsFromArray(someArray) {
    var newArray = [];
    for(var index = 0; index < someArray.length; index++) {
        if(someArray[index]) {
            newArray.push(someArray[index]);
        }
    }
    return newArray;
}

W rzeczywistości jest to bardziej ogólne rozwiązanie:

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]

Wpadasz na pomysł - wtedy możesz mieć inne typy funkcji filtrów. Prawdopodobnie więcej niż potrzebujesz, ale czułem się hojny ...;)

Jason Bunting
źródło
7

Co z tym (ES6): Aby usunąć wartość Falsy z tablicy.

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"]
VIJAY P
źródło
6

Powinieneś użyć filtru, aby uzyskać tablicę bez pustych elementów. Przykład na ES6

const array = [1, 32, 2, undefined, 3];
const newArray = array.filter(arr => arr);
Gapur Kassym
źródło
3

Ja po prostu dodając swój głos do powyższego „Call ES5 użytkownika Array..filter()z globalnym konstruktora” Golf-Hack, ale sugerujemy użycie Objectzamiast String, Booleanalbo Numberjak zasugerowano powyżej.

W szczególności ES5 filter()już nie wyzwala undefinedelementów w tablicy; więc funkcja, która uniwersalnie zwraca true, która zwraca wszystkiefilter() trafienia elementów , z konieczności zwróci tylko nie- undefinedelementy:

> [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]

Pisanie ...(function(){return true;})jest jednak dłuższe niż pisanie ...(Object); a wartość zwracana przez Objectkonstruktor będzie w każdym przypadku jakimś przedmiotem. W przeciwieństwie do sugerowanych powyżej konstruktorów boksowania pierwotnego, żadna możliwa wartość obiektu nie jest falsey, a zatem w ustawieniu boolowskim Objectjest krótką ręką 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]
ELLIOTTCABLE
źródło
1
UWAGA: filtr (ciąg) i filtr (obiekt) nie odfiltrowują wartości null ani liczb. Ponieważ konstruktor jest również funkcją, można przekazać ciąg znaków do filtru, tzn. someArray.filter(String);Faktycznie jest on równoważny someArray.filter(function(x){ return String(x); });. Jeśli chcesz usunąć wszystkie wartości fałszowania, someArray.filter(Boolean);usuwa 0, -0, NaN, false, '', null i undefined.
robocat
1
Ładna odpowiedź, chociaż zastanawiam się nad wydajnością wywołania Objectkonstruktora w przeciwieństwie do return truemetody. @robocat OP poprosił o usunięcie pustych elementów, a nie zer.
Alnitak
Wolę najkrótsze i najczystsze rozwiązanie, z wyjątkiem ciasnych pętli. Przypuszczam, że osobiste preferencje. (=
ELLIOTTCABLE
3

Kiedy użyłem wyżej głosowanej odpowiedzi, pierwszy przykład, otrzymywałem poszczególne znaki dla długości łańcucha większej niż 1. Poniżej znajduje się moje rozwiązanie tego problemu.

var stringObject = ["", "some string yay", "", "", "Other string yay"];
stringObject = stringObject.filter(function(n){ return n.length > 0});

Zamiast nie wracać, jeśli jest niezdefiniowany, zwracamy, jeśli długość jest większa niż 0. Mam nadzieję, że ktoś komuś pomoże.

Zwroty

["some string yay", "Other string yay"]
John Miller
źródło
+1, ponieważ jest to bardzo praktyczne i dokładnie to, czego zwykle potrzebuję do pracy z tablicami ciągów, ale pamiętaj, że usuwa to liczby (jeśli nie są w postaci ciągu), ponieważ nie mają długości. ["", "some string yay", "", "", 123, "Other string yay"].filter(function(n){ return n.length > 0}) //gives your same result removing 123Zastępowanie tej funkcji. .. z String, jak na ironię, pozostawia liczby, ale dałby taki sam wynik w podanej tablicy.
aamarks
3
var data = [null, 1,2,3];
var r = data.filter(function(i){ return i != null; })

console.log(r) 

[1,2,3]

KARTHIKEYAN.A
źródło
Jest to oczywiście poprawny sposób na zrobienie tego i powinien być na szczycie!
Martin Andersson
2

Co z tym:

js> [1,2,,3,,3,,,0,,,4,,4,,5,,6,,,,].filter(String).join(',')
1,2,3,3,0,4,4,5,6
JessyNinja
źródło
6
join() === join(','):)
pimvdb
1

To działa, przetestowałem go w AppJet (możesz skopiować i wkleić kod na jego IDE i nacisnąć „przeładuj”, aby zobaczyć, jak działa, nie trzeba tworzyć konta)

/* 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]
*/
Joe Pineda
źródło
1
Wydaje się, że działa to „przypadkowo”, ponieważ polega na wyliczeniu kluczy for ... in, co powoduje pominięcie brakujących elementów. Test undefinedsłuży tylko do usunięcia rzeczywistych elementów, które są jawnie ustawione na tę wartość.
Alnitak
1

Innym sposobem na to jest skorzystanie z właściwości length tablicy: spakuj elementy inne niż null po lewej stronie tablicy, a następnie zmniejsz długość. Jest to algorytm lokalny - nie przydziela pamięci, co jest bardzo złe dla śmieciarza - i ma bardzo dobre zachowanie w najlepszym / średnim / najgorszym przypadku.

To rozwiązanie, w porównaniu do innych tutaj, jest od 2 do 50 razy szybsze w Chrome i 5 do 50 razy szybsze w Firefox, jak można zobaczyć tutaj: http://jsperf.com/remove-null-items-from-array

Poniższy kod dodaje do tablicy macierz, której nie można wyliczyć, „removeNull”, która zwraca „to” do łączenia łańcuchowego:

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 } ) ;
GameAlchemist
źródło
Fajna odpowiedź, chociaż dobrze byłoby zobaczyć kilka przypadków testowych, aby pokazać to w akcji!
Alnitak
2
Ta odpowiedź jest bardzo fascynujące, ale trochę przypomina mi spojrzenie na komputerze zbudowany w 1945 roku, kiedy mam smartphone: arr.filter(e => e).
agm1984
1
foo = [0, 1, 2, "", , false, 3, "four", null]

foo.filter(function(e) {
    return e === 0 ? '0' : e
})

zwroty

[0, 1, 2, 3, "four"]
sqram
źródło
1

„Niewłaściwe” użycie pętli for ... in (object-member). => Tylko prawdziwe wartości pojawiają się w ciele pętli.

// --- 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);
michael.zech
źródło
kod jest poprawny, komentarz jest błędny. Czynność polegająca na użyciu for ... inpowoduje usunięcie niezdefiniowanych kluczy z tablicy, ale tak naprawdę nie ma tutaj kodu, który w przeciwnym razie akceptowałby tylko „prawdziwe” wartości
Alnitak
1

To może ci pomóc: 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));
            });
        };
Sandeep M.
źródło
1
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);

Wynik:

Pracuję nad nodejs

Usunie pusty element z tablicy i wyświetli inny element.

Jitendra virani
źródło
wyjście: „Pracuję nad nodejs”. usunie pusty element z tablicy i wyświetli inny element.
Jitendra virani
Poprawiłem twoją odpowiedź. Spróbuj udzielić prostej, jasnej i czytelnej odpowiedzi;)
GGO
1

Usuwanie wszystkich pustych elementów

Jeśli tablica zawiera puste obiekty, tablice i ciągi obok innych pustych elementów, możemy je usunąć za pomocą:

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))

Proste kompaktowanie (usuwanie pustych elementów z tablicy)

Z 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)

Ze zwykłym Javascriptem ->

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)

Zlatko Alomerovic
źródło
0

Filtrowanie nieprawidłowych wpisów za pomocą wyrażenia regularnego

array = array.filter(/\w/);
filter + regexp
lcabral
źródło
czy to działa? pokazuje błąd TypeError: [obiekt RegExp] nie jest funkcją
FreeLightman
0

Najlepszym sposobem na usunięcie pustych elementów jest użycie Array.prototype.filter() , jak już wspomniano w innych odpowiedziach.

Niestety Array.prototype.filter()nie jest obsługiwany przez IE <9. Jeśli nadal potrzebujesz obsługi IE8 lub nawet starszej wersji IE, możesz użyć następującego polifillu, aby dodać obsługę Array.prototype.filter()w tych przeglądarkach:

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;
  };
}
John Slegers
źródło