Usuń puste elementy tablicy


783

Niektóre elementy w mojej tablicy są pustymi ciągami na podstawie tego, co użytkownik przesłał. Muszę usunąć te elementy. Mam to:

foreach($linksArray as $link)
{
    if($link == '')
    {
        unset($link);
    }
}
print_r($linksArray);

Ale to nie działa. $linksArraywciąż ma puste elementy. Próbowałem również zrobić to z empty()funkcją, ale wynik jest taki sam.


1
Pomyślałem, że warto wspomnieć, że powyższy kod nie działa, ponieważ unset (...) działa na zmiennej utworzonej przez pętlę foreach, a nie na oryginalnej tablicy, która oczywiście pozostaje taka, jak przed pętlą.
Zapisane

if (! empty ($ link)) {echo $ link; } to działa dla mnie
Shiplu

Zmieniasz link $, który nie jest potwierdzony! użyj foreach ($ linksArray jako $ key => $ link) unset (linksArray [$ key])
TD_Nijboer

Odpowiedzi:


1547

Gdy masz do czynienia z tablicą ciągów znaków, możesz po prostu użyć array_filter(), który wygodnie obsługuje to wszystko za Ciebie:

print_r(array_filter($linksArray));

Należy pamiętać, że jeśli nie zostanie dostarczone wywołanie zwrotne , wszystkie wpisy w tablicy równej FALSE(patrz konwersja na wartość logiczną ) zostaną usunięte. Więc jeśli chcesz zachować elementy, które są np. Ciągiem dokładnym '0', będziesz potrzebował niestandardowego wywołania zwrotnego:

// PHP 7.4 and later
print_r(array_filter($linksArray, fn($value) => !is_null($value) && $value !== ''));

// PHP 5.3 and later
print_r(array_filter($linksArray, function($value) { return !is_null($value) && $value !== ''; }));

// PHP < 5.3
print_r(array_filter($linksArray, create_function('$value', 'return $value !== "";')));

16
array_filterpowinien usunąć puste elementy. A jeśli definicja PHP pusta nie jest taka sama jak twoja definicja, możesz wypełnić opcję wywołania zwrotnego anonimową funkcją, która wyrzuca niechciane elementy. Najwyraźniej musisz mieć php 5.3 lub nowszy, aby korzystać z anonimowych połączeń zwrotnych. stackoverflow.com/questions/2412299/…
Buttle Butkus

76
uważaj, że array_filter nie indeksuje ponownie indeksów tablic (może wystąpić problem z użyciem tablicy procesów w instrukcji for). Więc zawiń to wszystko za pomocą funkcji array_values.
Michał - wereda-net

8
Odpowiedź jest niepoprawna, ponieważ spowoduje również usunięcie falseelementów. ( php.net/manual/en/function.array-filter.php )
pliashkou

5
@Deji próbowałeś wydrukować tę tablicę przed jej odfiltrowaniem? Myślę, że ustawienie adrugiego czasu po prostu resetuje pierwszy.
Cullub,

5
@Cranio: który jest już objęty innym komentarzem. To nie jest niepoprawne, ale być może szersze niż twoje wymagania. To nie znaczy, że inni ludzie nadal nie mogą znaleźć pomocy; w końcu jeśli wszystko, co masz, to ciągi znaków w tablicy, ta odpowiedź usunie tylko puste.
Martijn Pieters

169

Możesz użyć array_filterdo usunięcia pustych elementów:

$emptyRemoved = array_filter($linksArray);

Jeśli masz (int) 0w swojej tablicy, możesz użyć następujących czynności:

$emptyRemoved = remove_empty($linksArray);

function remove_empty($array) {
  return array_filter($array, '_remove_empty_internal');
}

function _remove_empty_internal($value) {
  return !empty($value) || $value === 0;
}

EDYCJA: Może twoje elementy same w sobie nie są puste, ale zawierają jedną lub więcej spacji ... Możesz użyć następujących przed użyciemarray_filter

$trimmedArray = array_map('trim', $linksArray);

10
Właśnie dodałem go do akceptowanej odpowiedzi BoltClock, możesz po prostu zrobić array_filter ($ foo, 'strlen'), aby uniknąć problemu „0” i usunąć tylko te o zerowej długości.
AB Carroll

2
@nezZario: Zakładając, że masz tylko scalarelementy w tablicy tak. W przeciwnym razie nie możesz tego zrobić.
Andrew Moore,

2
Korzystanie z lambda dla php> = 5.3function remove_empty($array) { return array_filter($array, function($value){return !empty($value) || $value === 0;}); }
Viral

1
array_map()zrobiłem magię, bo miałem puste miejsca w tych pustych tablicach!
Prodigy,

126

Najpopularniejsza odpowiedź na ten temat jest absolutnie NIEPRAWIDŁOWA.

Rozważ następujący skrypt PHP:

<?php
$arr = array('1', '', '2', '3', '0');
// Incorrect:
print_r(array_filter($arr));
// Correct:
print_r(array_filter($arr, 'strlen'));

Dlaczego to? Ponieważ łańcuch zawierający pojedynczy znak „0” również ma wartość logiczną „fałsz”, więc nawet jeśli nie jest to pusty ciąg, nadal będzie filtrowany. To byłby błąd.

Przekazywanie wbudowanej funkcji strlen jako funkcji filtrowania będzie działać, ponieważ zwraca niezerową liczbę całkowitą dla niepustego ciągu i zerową liczbę całkowitą dla pustego ciągu. Niezerowe liczby całkowite zawsze są przetwarzane na wartość logiczną, podczas gdy zerowe liczby całkowite zawsze są przekształcane na fałsz, gdy są przekształcane na wartości logiczne.

Tak więc absolutna, ostateczna, poprawna odpowiedź to:

$arr = array_filter($arr, 'strlen');

3
Zgoda. To powinna być zaakceptowana odpowiedź dla tych, których tablica zawiera ciągi znaków
mwieczorek

2
Pozytywne. Lepsza odpowiedź niż wiele innych, należy jednak zauważyć, że obecnie akceptowana odpowiedź nie jest technicznie niepoprawna, ponieważ „puste” w rzeczywistości ma specjalne znaczenie w PHP. (Niektóre wartości, które kwalifikują się jako "pusta": 0, "", null)
rinogo

5
Nie są niepoprawne, wszystko zależy od kontekstu. W niektórych przypadkach zachowanie wartości 0 może być ważne. Więc proszę, nie mówcie, że wszyscy się mylą oprócz ciebie
Macr1408,

6
Dzieje się tak, jeśli tablica zawiera inną tablicę:strlen() expects parameter 1 to be string, array given
hpaknia

Można powiedzieć, że może to być również dobre podejście (zamiast mówić inne niepoprawne), aby osiągnąć pożądane działania. Zasadniczo nie wszystkie przypadki są podobne. Chociaż takie podejście działa w moim przypadku.
MR_AMDEV

102
$linksArray = array_filter($linksArray);

„Jeśli nie zostanie dostarczone wywołanie zwrotne, wszystkie wpisy wejściowe równe FAŁSZ zostaną usunięte.” - http://php.net/manual/en/function.array-filter.php


4
Próbowałem też tego po problemie z Google. Niestety pozostawia to dla mnie puste elementy.
Czy

18
spowoduje to również usunięcie „0”
OIS

2
@Will: jesteś pewien? Usuwa również puste ciągi, pomyślnie to przetestowałem. Może twoje wartości wejściowe zawierają spacje i powinny zostać wcześniej przycięte. Zgodnie z regułami konwersji typu boolean pusty łańcuch jest oceniany na false, a zatem jest usuwany przez array_filter.
acme

52
    $myarray = array_filter($myarray, 'strlen');  //removes null values but leaves "0"
    $myarray = array_filter($myarray);            //removes all null values

strlen usuwa również fałsz :(
justnorris

42

Możesz po prostu zrobić

array_filter($array)

array_filter: "Jeśli nie zostanie podane wywołanie zwrotne, wszystkie wpisy wejściowe równe FAŁSZ zostaną usunięte." Oznacza to, że elementy o wartościach NULL, 0, „0”, „”, FALSE, array () również zostaną usunięte.

Druga opcja robi

array_diff($array, array(''))

który usunie elementy o wartości NULL, '' i FALSE.

Mam nadzieję że to pomoże :)

AKTUALIZACJA

Oto przykład.

$a = array(0, '0', NULL, FALSE, '', array());

var_dump(array_filter($a));
// array()

var_dump(array_diff($a, array(0))) // 0 / '0'
// array(NULL, FALSE, '', array());

var_dump(array_diff($a, array(NULL))) // NULL / FALSE / ''
// array(0, '0', array())

Podsumowując:

  • 0 lub „0” usunie 0 i „0”
  • NULL, FALSE lub „” usunie NULL, FALSE i „”

36
foreach($linksArray as $key => $link) 
{ 
    if($link === '') 
    { 
        unset($linksArray[$key]); 
    } 
} 
print_r($linksArray); 

4
Zwięzłe, czytelne i bezpieczne rozwiązanie, które nie usuwa falsei 0. Biorąc pod uwagę, że została opublikowana w tej samej minucie co zaakceptowana odpowiedź (która jest niebezpieczna i niepoprawna), mogę założyć, że twoje 8 głosów pozytywnych w porównaniu do odpowiedzi zaakceptowanej 649 wynika z tego, że jest to rozwiązanie jednowierszowe.
rybo111

@ rybo111 - być może, choć użycie tej logiki w wywołaniu zwrotnym array_filter()byłoby czystszym podejściem niż foreach()pętla
Mark Baker

Być może szybciej, ale twoje rozwiązanie jest najbardziej czytelne, co jest ważne. Dla tych, którzy używają twojego rozwiązania wymagającego trim(), polecamif(is_string($link) && trim($link) === '')
rybo111

33

Kolejna linijka do usuwania pustych ("" pustych ciągów) elementów z tablicy.

$array = array_filter($array, function($a) {return $a !== "";});

Uwaga: Ten kod celowo utrzymuje null, 0a falseelementy.


A może najpierw chcesz przyciąć elementy tablicy:

$array = array_filter($array, function($a) {
    return trim($a) !== "";
});

Uwaga: ten kod usuwa również nulli falseelementy.


3
Właśnie tego potrzebowałem, a to jest również zgodne ze starszymi PHP , dzięki! ;-)
Stano

1
@JohnK Wrong. Aby to zrobić dokładnie tak, jak użytkownik chce oddzwonienia, konieczne jest , chyba że chcesz usunąć zera alzo i inne wartości falsey.
Cranio,

Och ... to jest absolutnie cudowne. Powinien być zaakceptowany.
Henrik Petterson

20

W skrócie:

To jest mój sugerowany kod:

$myarray =  array_values(array_filter(array_map('trim', $myarray), 'strlen'));

Wyjaśnienie:

Myślę, że użycie array_filterjest dobre, ale niewystarczające, ponieważ wartości są podobne spacedo \n... i trzymaj się tablicy, a to zwykle jest złe.

Więc proponuję użyć mieszanki array_filteri array_map.

array_mapsłuży do przycinania, array_filtersłuży do usuwania pustych wartości, strlensłuży do zachowania 0wartości i array_valuessłuży do ponownego indeksowania, jeśli zajdzie taka potrzeba.

Próbki:

$myarray = array("\r", "\n", "\r\n", "", " ", "0", "a");

// "\r", "\n", "\r\n", " ", "a"
$new1 = array_filter($myarray);

// "a"
$new2 = array_filter(array_map('trim', $myarray));

// "0", "a"
$new3 = array_filter(array_map('trim', $myarray), 'strlen');

// "0", "a" (reindex)
$new4 = array_values(array_filter(array_map('trim', $myarray), 'strlen'));

var_dump($new1, $new2, $new3, $new4);

Wyniki:

array(5) {
  [0]=>
" string(1) "
  [1]=>
  string(1) "
"
  [2]=>
  string(2) "
"
  [4]=>
  string(1) " "
  [6]=>
  string(1) "a"
}
array(1) {
  [6]=>
  string(1) "a"
}
array(2) {
  [5]=>
  string(1) "0"
  [6]=>
  string(1) "a"
}
array(2) {
  [0]=>
  string(1) "0"
  [1]=>
  string(1) "a"
}

Test online:

http://phpio.net/s/5yg0



12

Najczęściej głosowana odpowiedź jest nieprawidłowa lub przynajmniej nie do końca prawdziwa, ponieważ OP mówi tylko o pustych ciągach. Oto dokładne wyjaśnienie:

Co oznacza pusty ?

Przede wszystkim musimy uzgodnić, co oznacza pusty . Czy chcesz odfiltrować:

  1. tylko puste ciągi („”)?
  2. te ściśle fałszywe wartości? ( $element === false)
  3. z falsey wartości? (tj. 0, 0,0, „”, „0”, NULL, tablica () ...)
  4. odpowiednik funkcji PHP empty()?

Jak odfiltrować wartości

Aby odfiltrować tylko puste ciągi :

$filtered = array_diff($originalArray, array(""));

Aby odfiltrować tylko ściśle fałszywe wartości, musisz użyć funkcji zwrotnej :

$filtered = array_diff($originalArray, 'myCallback');
function myCallback($var) {
    return $var === false;
}

Oddzwanianie jest również przydatne w każdej kombinacji, w której chcesz odfiltrować wartości „falsey”, z wyjątkiem niektórych. (Na przykład filtruj wszystko nulli falseitd., Pozostawiając tylko 0):

$filtered = array_filter($originalArray, 'myCallback');
function myCallback($var) {
    return ($var === 0 || $var === '0');
}

Trzeci i czwarty przypadek są (w końcu dla naszych celów) równoważne, a do tego wystarczy użyć domyślnego:

$filtered = array_filter($originalArray);

2
Jeśli chcesz wyjąć nulli falsepozostawić 0, możesz również użyć wbudowanej strlenfunkcji php jako oddzwaniania.
Cullub

10

Musiałem to zrobić, aby zachować wartość tablicy (ciąg) 0

$url = array_filter($data, function ($value) {
  return (!empty($value) || $value === 0 || $value==='0');
});


9

Dla tablicy wielowymiarowej

$data = array_map('array_filter', $data);
$data = array_filter($data);

9
$out_array = array_filter($input_array, function($item) 
{ 
    return !empty($item['key_of_array_to_check_whether_it_is_empty']); 
}
);

9
function trim_array($Array)
{
    foreach ($Array as $value) {
        if(trim($value) === '') {
            $index = array_search($value, $Array);
            unset($Array[$index]);
        }
    }
    return $Array;
}

7

Używam następującego skryptu, aby usunąć puste elementy z tablicy

for ($i=0; $i<$count($Array); $i++)
  {
    if (empty($Array[$i])) unset($Array[$i]);
  }

7

Chcę po prostu stanowić alternatywę dla pętli ... również eliminując luki w kluczach ...

W moim przypadku chciałem zachować sekwencyjne klucze tablicy po zakończeniu operacji (nie tylko liczby nieparzyste, na co się gapiłem. Konfigurowanie kodu w celu wyszukiwania tylko nieparzystych kluczy wydawało mi się kruche i nieprzydatne na przyszłość.)

Szukałem czegoś takiego: http://gotofritz.net/blog/howto/removing-empty-array-elements-php/

Kombinacja array_filter i array_slice załatwia sprawę.

$example = array_filter($example); $example = array_slice($example,0);

Nie ma pojęcia na temat wydajności ani testów porównawczych, ale działa.


Myślę, że wartości_wartości miałyby taki sam wynik jak wartość macierzy. Wydaje się to bardziej intuicyjne, jeśli chodzi o późniejsze czytanie kodu i zrozumienie, co robi.
arlomedia,

6
$my = ("0"=>" ","1"=>"5","2"=>"6","3"=>" ");   

foreach ($my as $key => $value) {
    if (is_null($value)) unset($my[$key]);
}

foreach ($my as $key => $value) {
    echo   $key . ':' . $value . '<br>';
} 

wynik

1: 5

2: 6



5

Tylko jedna linia: aktualizacja (dzięki @suther):

$array_without_empty_values = array_filter($array);

nie potrzebujesz drugiego parametru: $ clean_array = array_filter ($ dirty_array);
suther

4

użyj array_filterfunkcji, aby usunąć puste wartości:

$linksArray = array_filter($linksArray);
print_r($linksArray);

Chce usunąć puste ciągi , które nie są równoważne pustym wartościom.
Cranio,

4

Usuń puste elementy tablicy

function removeEmptyElements(&$element)
{
    if (is_array($element)) {
        if ($key = key($element)) {
            $element[$key] = array_filter($element);
        }

        if (count($element) != count($element, COUNT_RECURSIVE)) {
            $element = array_filter(current($element), __FUNCTION__);
        }

        return $element;
    } else {
        return empty($element) ? false : $element;
    }
}

$data = array(
    'horarios' => array(),
    'grupos' => array(
        '1A' => array(
            'Juan' => array(
                'calificaciones' => array(
                    'Matematicas' => 8,
                    'Español' => 5,
                    'Ingles' => 9,
                ),
                'asistencias' => array(
                    'enero' => 20,
                    'febrero' => 10,
                    'marzo' => '',
                )
            ),
            'Damian' => array(
                'calificaciones' => array(
                    'Matematicas' => 10,
                    'Español' => '',
                    'Ingles' => 9,
                ),
                'asistencias' => array(
                    'enero' => 20,
                    'febrero' => '',
                    'marzo' => 5,
                )
            ),
        ),
        '1B' => array(
            'Mariana' => array(
                'calificaciones' => array(
                    'Matematicas' => null,
                    'Español' => 7,
                    'Ingles' => 9,
                ),
                'asistencias' => array(
                    'enero' => null,
                    'febrero' => 5,
                    'marzo' => 5,
                )
            ),
        ),
    )
);

$data = array_filter($data, 'removeEmptyElements');
var_dump($data);

to działa!


3

Zgodnie z twoją metodą, możesz po prostu złapać te elementy w innej tablicy i użyć tego w następujący sposób,

foreach($linksArray as $link){
   if(!empty($link)){
      $new_arr[] = $link
   }
}

print_r($new_arr);

1

spróbuj tego ** ** Przykład

$or = array(
        'PersonalInformation.first_name' => $this->request->data['User']['first_name'],
        'PersonalInformation.last_name' => $this->request->data['User']['last_name'],
        'PersonalInformation.primary_phone' => $this->request->data['User']['primary_phone'],
        'PersonalInformation.dob' => $this->request->data['User']['dob'],
        'User.email' => $this->request->data['User']['email'],
    );



 $or = array_filter($or);

    $condition = array(
        'User.role' => array('U', 'P'),
        'User.user_status' => array('active', 'lead', 'inactive'),
        'OR' => $or
    );

1
co to jest? istnieje mnóstwo innych bardzo istotnych odpowiedzi. Co tu dodajesz?
Félix Gagnon-Grenier

sprawdź adres URL jakie było pytanie !! / * usuń pusty element tablicy * /
Ashish pathak

1

Myślę, że array_walk jest tutaj bardziej odpowiedni

$linksArray = array('name', '        ', '  342', '0', 0.0, null, '', false);

array_walk($linksArray, function(&$v, $k) use (&$linksArray){
    $v = trim($v);
    if ($v == '')
        unset($linksArray[$k]);
});
print_r($linksArray);

Wynik:

Array
(
    [0] => name
    [2] => 342
    [3] => 0
    [4] => 0
)
  • Upewniliśmy się, że puste wartości są usuwane, nawet jeśli użytkownik doda więcej niż jedną spację
  • Odciąliśmy również puste miejsca od prawidłowych wartości

  • Wreszcie tylko puste (Null), (Boolean False) i ('') będą uważane za puste ciągi

Jeśli chodzi o Falseto, że można go usunąć, ponieważ AFAIK użytkownik nie może przesłać wartości boolowskich.


0

W przypadku tego typu rzeczy o wiele lepiej jest wyraźnie powiedzieć, czego chcesz, a czego nie.

Pomoże to następnemu facetowi nie dać się zaskoczyć zachowaniem array_filter()bez oddzwaniania. Na przykład skończyłem na tym pytaniu, ponieważ zapomniałem, czy je array_filter()usuwa, NULLczy nie. Zmarnowałem czas, kiedy mogłem po prostu skorzystać z poniższego rozwiązania i otrzymać odpowiedź.

Logika jest również angnostyczna w tym sensie, że kod można skopiować na inny język bez konieczności rozumienia zachowania funkcji php, na przykład array_filtergdy nie jest przekazywane żadne wywołanie zwrotne.

W moim rozwiązaniu na pierwszy rzut oka widać, co się dzieje. Usuń warunek, aby coś zachować, lub dodaj nowy warunek, aby przefiltrować dodatkowe wartości.

Zignoruj ​​faktyczne użycie, array_filter()ponieważ po prostu przekazuję mu niestandardowe wywołanie zwrotne - możesz, jeśli chcesz, wyodrębnić to do własnej funkcji. Po prostu używam go jako cukru na foreachpętlę.

<?php

$xs = [0, 1, 2, 3, "0", "", false, null];

$xs = array_filter($xs, function($x) {
    if ($x === null) { return false; }
    if ($x === false) { return false; }
    if ($x === "") { return false; }
    if ($x === "0") { return false; }
    return true;
});

$xs = array_values($xs); // reindex array   

echo "<pre>";
var_export($xs);

Inną zaletą tego podejścia jest to, że można podzielić predykaty filtrowania na funkcję abstrakcyjną, która filtruje pojedynczą wartość na tablicę i tworzy rozwiązanie kompozycyjne.

Zobacz ten przykład i wbudowane komentarze dla danych wyjściowych.

<?php

/**
 * @param string $valueToFilter
 *
 * @return \Closure A function that expects a 1d array and returns an array
 *                  filtered of values matching $valueToFilter.
 */
function filterValue($valueToFilter)
{
    return function($xs) use ($valueToFilter) {
        return array_filter($xs, function($x) use ($valueToFilter) {
            return $x !== $valueToFilter;
        });
    };
}

// partially applied functions that each expect a 1d array of values
$filterNull = filterValue(null);
$filterFalse = filterValue(false);
$filterZeroString = filterValue("0");
$filterEmptyString = filterValue("");

$xs = [0, 1, 2, 3, null, false, "0", ""];

$xs = $filterNull($xs);        //=> [0, 1, 2, 3, false, "0", ""]
$xs = $filterFalse($xs);       //=> [0, 1, 2, 3, "0", ""]
$xs = $filterZeroString($xs);  //=> [0, 1, 2, 3, ""]
$xs = $filterEmptyString($xs); //=> [0, 1, 2, 3]

echo "<pre>";
var_export($xs); //=> [0, 1, 2, 3]

Teraz możesz dynamicznie utworzyć funkcję o nazwie filterer()using pipe(), która zastosuje te częściowo zastosowane funkcje.

<?php

/**
 * Supply between 1..n functions each with an arity of 1 (that is, accepts
 * one and only one argument). Versions prior to php 5.6 do not have the
 * variadic operator `...` and as such require the use of `func_get_args()` to
 * obtain the comma-delimited list of expressions provided via the argument
 * list on function call.
 *
 * Example - Call the function `pipe()` like:
 *
 *   pipe ($addOne, $multiplyByTwo);
 *
 * @return closure
 */
function pipe()
{
    $functions = func_get_args(); // an array of callable functions [$addOne, $multiplyByTwo]
    return function ($initialAccumulator) use ($functions) { // return a function with an arity of 1
        return array_reduce( // chain the supplied `$arg` value through each function in the list of functions
            $functions, // an array of functions to reduce over the supplied `$arg` value
            function ($accumulator, $currFn) { // the reducer (a reducing function)
                return $currFn($accumulator);
            },
            $initialAccumulator
        );
    };
}

/**
 * @param string $valueToFilter
 *
 * @return \Closure A function that expects a 1d array and returns an array
 *                  filtered of values matching $valueToFilter.
 */
function filterValue($valueToFilter)
{
    return function($xs) use ($valueToFilter) {
        return array_filter($xs, function($x) use ($valueToFilter) {
            return $x !== $valueToFilter;
        });
    };
}

$filterer = pipe(
    filterValue(null),
    filterValue(false),
    filterValue("0"),
    filterValue("")
);

$xs = [0, 1, 2, 3, null, false, "0", ""];
$xs = $filterer($xs);

echo "<pre>";
var_export($xs); //=> [0, 1, 2, 3]
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.