web-dev-qa-db-ja.com

多次元配列から空の要素とサブ配列を再帰的に削除します

PHPの配列から空の要素を削除するという昔からの問題に対する単純で直接的な解決策を見つけることができないようです。

私の入力配列は次のようになります。

_Array ( [0] => Array ( [Name] => [EmailAddress] => ) ) 
_

(データがもっとある場合は、そうではないかもしれませんが...)

上記のようになったら、処理した後は完全に空にします。

したがって、print_r($array);は次のように出力します。

_Array ( )
_

$arrayX = array_filter($arrayX);を実行しても、同じ _print_r_の出力が得られます。しかし、私が調べたところはどこでも、これがPHP5で空の配列要素を削除する最も簡単な方法であることを示唆しています。

$arrayX = array_filter($arrayX,'empty_array');も試しましたが、次のエラーが発生しました。

警告:array_filter()[function.array-filter]:2番目の引数 'empty_array'は有効なコールバックである必要があります

私は何が間違っているのですか?

19
Chuck Le Butt

array_map() を使用して、$array内のすべての配列にフィルターを適用してみてください。

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

デモ: http://codepad.org/xfXEeApj

29
Wesley Murch

これを行う方法の例はたくさんあります。 docs を試してみてください(最初のコメントを参照)。

function array_filter_recursive($array, $callback = null) {
    foreach ($array as $key => & $value) {
        if (is_array($value)) {
            $value = array_filter_recursive($value, $callback);
        }
        else {
            if ( ! is_null($callback)) {
                if ( ! $callback($value)) {
                    unset($array[$key]);
                }
            }
            else {
                if ( ! (bool) $value) {
                    unset($array[$key]);
                }
            }
        }
    }
    unset($value);

    return $array;
}

この例では実際にはarray_filterを使用していませんが、要点はわかります。

5
jeremyharris

受け入れられた回答は、OPが要求したことを正確に実行しません。空の配列を含め、falseと評価されるすべての値を再帰的に削除する場合は、次の関数を使用します。

function array_trim($input) {
    return is_array($input) ? array_filter($input, 
        function (& $value) { return $value = array_trim($value); }
    ) : $input;
}

または、必要に応じて返品条件を変更することもできます。次に例を示します。

{ return !is_array($value) or $value = array_trim($value); }

空の配列のみを削除したい場合。または、条件を変更して、「」またはfalseまたはnullなどのみをテストすることもできます。

5
Alain

Jeremyharrisの提案に続いて、これは私がそれを機能させるためにそれを変更する必要があった方法です:

function array_filter_recursive($array) {
   foreach ($array as $key => &$value) {
      if (empty($value)) {
         unset($array[$key]);
      }
      else {
         if (is_array($value)) {
            $value = array_filter_recursive($value);
            if (empty($value)) {
               unset($array[$key]);
            }
         }
      }
   }

   return $array;
}
3
CodedMonkey

試してみてください:

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

例:

$array[0] = array(
   'Name'=>'',
   'EmailAddress'=>'',
);
print_r($array);

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

print_r($array);

出力:

Array
(
    [0] => Array
        (
            [Name] => 
            [EmailAddress] => 
        )
)

Array
(
)
1
joseantgv

array_filter()は、デフォルトでは型依存ではありません。これは、zero-ish、false-y、null、空の値が削除されることを意味します。フォローする私のリンクは、この点を示しています。

OPのサンプル入力配列は2次元です。データ構造が静的である場合、再帰は必要ありません。多次元配列から長さゼロの値をフィルタリングしたい人のために、静的2次元メソッドと再帰メソッドを提供します。

静的2次元配列:このコードは、第2レベルの要素に対して「ゼロセーフ」フィルターを実行してから、空のサブ配列を削除します:( このメソッドが異なる(よりトリッキーな)配列データで機能することを確認するには、このデモを参照してください

_$array=[
    ['Name'=>'','EmailAddress'=>'']
];   

var_export(
    array_filter(  // remove the 2nd level in the event that all subarray elements are removed
        array_map(  // access/iterate 2nd level values
            function($v){
                return array_filter($v,'strlen');  // filter out subarray elements with zero-length values
            },$array  // the input array
        )
    )
);
_

ワンライナーと同じコードは次のとおりです。

_var_export(array_filter(array_map(function($v){return array_filter($v,'strlen');},$array)));
_

出力(元々OPによって指定されたとおり):

_array (
)
_

*空のサブ配列を削除したくない場合は、外側のarray_filter()呼び出しを削除するだけです。


深さが不明な多次元配列の再帰的方法:配列内のレベル数が不明な場合、再帰は論理的な手法です。次のコードは、各サブアレイを処理し、長さがゼロの値と空のサブアレイを削除します。 これは、いくつかのサンプル入力を含むこのコードのデモです。

_$array=[
    ['Name'=>'','Array'=>['Keep'=>'Keep','Drop'=>['Drop2'=>'']],'EmailAddress'=>'','Pets'=>0,'Children'=>null],
    ['Name'=>'','EmailAddress'=>'','FavoriteNumber'=>'0']
];

function removeEmptyValuesAndSubarrays($array){
   foreach($array as $k=>&$v){
        if(is_array($v)){
            $v=removeEmptyValuesAndSubarrays($v);  // filter subarray and update array
            if(!sizeof($v)){ // check array count
                unset($array[$k]);
            }
        }elseif(!strlen($v)){  // this will handle (int) type values correctly
            unset($array[$k]);
        }
   }
   return $array;
}

var_export(removeEmptyValuesAndSubarrays($array));
_

出力:

_array (
  0 => 
  array (
    'Array' => 
    array (
      'Keep' => 'Keep',
    ),
    'Pets' => 0,
  ),
  1 => 
  array (
    'FavoriteNumber' => '0',
  ),
)
_

誰かが私の再帰的メソッドを壊す入力配列を発見した場合は、コメントとして(最も単純な形式で)投稿してください。回答を更新します。

1
mickmackusa