それはおそらく初心者の質問ですが、私はすでにより長い時間ドキュメントを調べているので、解決策が見つかりません。各次元で内破を使用し、それらの文字列を_str_split
_で元に戻し、新しい単純な配列を作成できると考えました。ただし、結合パターンが値にも含まれていないかどうかは分からないため、_str_split
_を実行した後、元の値が壊れる可能性があります。
多次元配列内の配列にcombine($array1, $array2)
のようなものはありますか?
<?php
$aNonFlat = array(
1,
2,
array(
3,
4,
5,
array(
6,
7
),
8,
9,
),
10,
11
);
$objTmp = (object) array('aFlat' => array());
array_walk_recursive($aNonFlat, create_function('&$v, $k, &$t', '$t->aFlat[] = $v;'), $objTmp);
var_dump($objTmp->aFlat);
/*
array(11) {
[0]=>
int(1)
[1]=>
int(2)
[2]=>
int(3)
[3]=>
int(4)
[4]=>
int(5)
[5]=>
int(6)
[6]=>
int(7)
[7]=>
int(8)
[8]=>
int(9)
[9]=>
int(10)
[10]=>
int(11)
}
*/
?>
PHP 5.5.9-1ubuntu4.24(cli)でテスト済み(built:Mar 16 2018 12:32:06)
$array = your array
$result = call_user_func_array('array_merge', $array);
echo "<pre>";
print_r($result);
参照: http://php.net/manual/en/function.call-user-func-array.php
別の解決策があります(多次元配列で動作します):
function array_flatten($array) {
$return = array();
foreach ($array as $key => $value) {
if (is_array($value)){ $return = array_merge($return, array_flatten($value));}
else {$return[$key] = $value;}
}
return $return;
}
$array = Your array
$result = array_flatten($array);
echo "<pre>";
print_r($result);
これは1行で、非常に使いやすいです。
$result = array();
array_walk_recursive($original_array,function($v) use (&$result){ $result[] = $v; });
無名関数/クロージャ内では、非常に簡単に理解できます。 $v
は、$original_array
の値です。
// $array = your multidimensional array
$flat_array = array();
foreach(new RecursiveIteratorIterator(new RecursiveArrayIterator($array)) as $k=>$v){
$flat_array[$k] = $v;
}
また文書化されています: http://www.phpro.org/examples/Flatten-Array.html
function flatten_array($array, $preserve_keys = 0, &$out = array()) {
# Flatten a multidimensional array to one dimension, optionally preserving keys.
#
# $array - the array to flatten
# $preserve_keys - 0 (default) to not preserve keys, 1 to preserve string keys only, 2 to preserve all keys
# $out - internal use argument for recursion
foreach($array as $key => $child)
if(is_array($child))
$out = flatten_array($child, $preserve_keys, $out);
elseif($preserve_keys + is_string($key) > 1)
$out[$key] = $child;
else
$out[] = $child;
return $out;
}
PHPの ユーザーコメント (簡略化)および ここ からの別の方法:
function array_flatten_recursive($array) {
if (!$array) return false;
$flat = array();
$RII = new RecursiveIteratorIterator(new RecursiveArrayIterator($array));
foreach ($RII as $value) $flat[] = $value;
return $flat;
}
この方法の大きな利点は、フラット化中に再帰の深さが必要な場合に、再帰の深さを追跡できることです。
これは出力します:
$array = array(
'A' => array('B' => array( 1, 2, 3)),
'C' => array(4, 5)
);
print_r(array_flatten_recursive($array));
#Returns:
Array (
[0] => 1
[1] => 2
[2] => 3
[3] => 4
[4] => 5
)
具体的には、1レベルよりも深くない配列の配列(私がよく見かけるユースケース)がある場合は、array_merge
とsplat演算子で回避できます。
<?php
$notFlat = [[1,2],[3,4]];
$flat = array_merge(...$notFlat);
var_dump($flat);
出力:
array(4) {
[0]=>
int(1)
[1]=>
int(2)
[2]=>
int(3)
[3]=>
int(4)
}
Splat演算子は、配列の配列をarray_merge
の引数として配列のリストに効果的に変更します。
PHP 7では、ジェネレーターとジェネレーター委任(yield from
)配列をフラット化するには:
function array_flatten_iterator (array $array) {
foreach ($array as $value) {
if (is_array($value)) {
yield from array_flatten_iterator($value);
} else {
yield $value;
}
}
}
function array_flatten (array $array) {
return iterator_to_array(array_flatten_iterator($array), false);
}
例:
$array = [
1,
2,
[
3,
4,
5,
[
6,
7
],
8,
9,
],
10,
11,
];
var_dump(array_flatten($array));
PHP> = 5.3では、Luc Mの回答(最初の回答)に基づいて、次のようなクロージャーを使用できます。
array_walk_recursive($aNonFlat, function(&$v, $k, &$t){$t->aFlat[] = $v;}, $objTmp);
Create_function()を使用するときのように、関数のコードを引用符で囲む必要がないため、これが大好きです。
非再帰的ソリューション(ただし、順序を破壊する):
function flatten($ar) {
$toflat = array($ar);
$res = array();
while (($r = array_shift($toflat)) !== NULL) {
foreach ($r as $v) {
if (is_array($v)) {
$toflat[] = $v;
} else {
$res[] = $v;
}
}
}
return $res;
}
高階関数の使用(注:PHP 5.3で登場した インライン匿名関数 を使用しています):
function array_flatten($array) {
return array_reduce(
$array,
function($prev, $element) {
if (!is_array($element))
$prev[] = $element;
else
$prev = array_merge($prev, array_flatten($element));
return $prev;
},
array()
);
}
配列キーを失うことに問題がない場合は、次のように、array_values()を利用するコールバックとして再帰クロージャーを使用して多次元配列をフラット化し、このコールバックがarray_walk()のパラメーターであることを確認します。
<?php
$array = [1,2,3,[5,6,7]];
$nu_array = null;
$callback = function ( $item ) use(&$callback, &$nu_array) {
if (!is_array($item)) {
$nu_array[] = $item;
}
else
if ( is_array( $item ) ) {
foreach( array_values($item) as $v) {
if ( !(is_array($v))) {
$nu_array[] = $v;
}
else
{
$callback( $v );
continue;
}
}
}
};
array_walk($array, $callback);
print_r($nu_array);
前の例の欠点の1つは、簡単なコールバックとともにarray_walk_recursive()を使用する次のソリューションよりもはるかに多くのコードを記述する必要があることです。
<?php
$array = [1,2,3,[5,6,7]];
$nu_array = [];
array_walk_recursive($array, function ( $item ) use(&$nu_array )
{
$nu_array[] = $item;
}
);
print_r($nu_array);
ライブコード を参照してください
この例は、多次元配列から値を抽出する方法に関する詳細を隠し、前の例よりも望ましいようです。確かに、反復は発生しますが、再帰を伴うか制御構造を伴うかにかかわらず、array.cを熟読することによってのみ知ることができます。関数型プログラミングは結果を得るための細かい点ではなく入力と出力に焦点を当てているため、舞台裏での反復がどのように発生するか、つまりパースペクティブの雇用者がそのような質問を投げかけるまで心配する必要はありません。
/*consider $mArray as multidimensional array and $sArray as single dimensional array
this code will ignore the parent array
*/
function flatten_array2($mArray) {
$sArray = array();
foreach ($mArray as $row) {
if ( !(is_array($row)) ) {
if($sArray[] = $row){
}
} else {
$sArray = array_merge($sArray,flatten_array2($row));
}
}
return $sArray;
}
カオスによって提出された前のサンプル関数に基づく新しいアプローチは、マルチアレイの文字列キーを上書きするバグを修正します。
# Flatten a multidimensional array to one dimension, optionally preserving keys.
# $array - the array to flatten
# $preserve_keys - 0 (default) to not preserve keys, 1 to preserve string keys only, 2 to preserve all keys
# $out - internal use argument for recursion
function flatten_array($array, $preserve_keys = 2, &$out = array(), &$last_subarray_found)
{
foreach($array as $key => $child)
{
if(is_array($child))
{
$last_subarray_found = $key;
$out = flatten_array($child, $preserve_keys, $out, $last_subarray_found);
}
elseif($preserve_keys + is_string($key) > 1)
{
if ($last_subarray_found)
{
$sfinal_key_value = $last_subarray_found . "_" . $key;
}
else
{
$sfinal_key_value = $key;
}
$out[$sfinal_key_value] = $child;
}
else
{
$out[] = $child;
}
}
return $out;
}
Example:
$newarraytest = array();
$last_subarray_found = "";
$this->flatten_array($array, 2, $newarraytest, $last_subarray_found);
これを試すことができます:
function flat_an_array($a)
{
foreach($a as $i)
{
if(is_array($i))
{
if($na) $na = array_merge($na,flat_an_array($i));
else $na = flat_an_array($i);
}
else $na[] = $i;
}
return $na;
}
マルチレベル配列を1つに変換する簡単な方法を見つけました。配列をURL文字列に変換する関数「http_build_query」を使用します。次に、explodeで文字列を分割し、値をデコードします。
これがサンプルです。
$converted = http_build_query($data);
$rows = explode('&', $converted);
$output = array();
foreach($rows AS $k => $v){
list($kk, $vv) = explode('=', $v);
$output[ urldecode($kk) ] = urldecode($vv);
}
return $output;
シンプルなアプローチ。再帰を介して参照してください。
<?php
function flatten_array($simple){
static $outputs=array();
foreach ( $simple as $value)
{
if(is_array($value)){
flatten_array($value);
}
else{
$outputs[]=$value;
}
}
return $outputs;
}
$eg=['s'=>['p','n'=>['t']]];
$out=flatten_array($eg);
print_r($out);
?>
flatten 関数を Non-standard PHP library(NSPL) から使用できます。配列および反復可能なデータ構造で動作します。
assert([1, 2, 3, 4, 5, 6, 7, 8, 9] === flatten([[1, [2, [3]]], [[[4, 5, 6]]], 7, 8, [9]]));