它是可能的,在PHP中,在不使用递归或引用的情况下扁平化(bi/multi)维数组?

我只对值感兴趣,所以键可以忽略,我认为在array_map()和array_values()的行。


当前回答

这里有一个简单的方法:

$My_Array = array(1,2,array(3,4, array(5,6,7), 8), 9);

function checkArray($value) {
    foreach ($value as $var) {
        if ( is_array($var) ) {
            checkArray($var);
        } else {
            echo $var;
        }
    }
}

checkArray($My_Array);

其他回答

我只是想指出这是一个折叠,所以可以使用array_reduce

array_reduce($my_array, 'array_merge', array());

编辑:注意,这可以组成平任意数量的水平。我们可以通过以下几种方式做到这一点:

// Reduces one level
$concat   = function($x) { return array_reduce($x, 'array_merge', array()); };

// We can compose $concat with itself $n times, then apply it to $x
// This can overflow the stack for large $n
$compose  = function($f, $g) {
    return function($x) use ($f, $g) { return $f($g($x)); };
};
$identity = function($x) { return $x; };
$flattenA = function($n) use ($compose, $identity, $concat) {
    return  function($x) use ($compose, $identity, $concat, $n) {
        return ($n === 0)? $x
                         : call_user_func(array_reduce(array_fill(0, $n, $concat),
                                                       $compose,
                                                       $identity),
                                          $x);
    };
};

// We can iteratively apply $concat to $x, $n times
$uncurriedFlip     = function($f) {
    return  function($a, $b) use ($f) {
        return $f($b, $a);
    };
};
$iterate  = function($f) use ($uncurriedFlip) {
    return  function($n) use ($uncurriedFlip, $f) {
    return  function($x) use ($uncurriedFlip, $f, $n) {
        return ($n === 0)? $x
                         : array_reduce(array_fill(0, $n, $f),
                                        $uncurriedFlip('call_user_func'),
                                        $x);
    }; };
};
$flattenB = $iterate($concat);

// Example usage:
$apply    = function($f, $x) {
    return $f($x);
};
$curriedFlip = function($f) {
    return  function($a) use ($f) {
    return  function($b) use ($f, $a) {
        return $f($b, $a);
    }; };
};

var_dump(
    array_map(
        call_user_func($curriedFlip($apply),
                       array(array(array('A', 'B', 'C'),
                                   array('D')),
                             array(array(),
                                   array('E')))),
        array($flattenA(2), $flattenB(2))));

当然,我们也可以使用循环,但这个问题要求的是一个组合子函数,类似于array_map或array_values。

二维数组的解

请试试这个:

$array  = your array

$result = call_user_func_array('array_merge', $array);

echo "<pre>";
print_r($result);

编辑:8月21日-13日

下面是适用于多维数组的解决方案:

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

裁判:http://php.net/manual/en/function.call-user-func-array.php

如果你想保留中间键:

function flattenArray(array &$result, $value, string $key = "")
{
    if (!is_array($value)) {
        $result[$key] = $value;
        return $result;
    }
    foreach ($value as $subKey => $subArray) {
        $newKey = $key !== "" ? $key . "_" . $subKey : $subKey;
        flattenArray($result, $subArray, $newKey);
    }
    return $result;
}

$nestedArray = [
    "name" => "John",
    "pets" => [
        ["id" => 1, "name" => "snooop"],
        ["id" => 2, "name" => "medor"],
    ],
    "job" => ["title" => "developper"],
];

$intermediateResult = [];
$flattened = flattenArray($intermediateResult, $nestedArray);
var_dump($flattened);

这将输出:

array(6) {
["name"]=>
  string(4) "John"
        ["pets_0_id"]=>
  int(1)
  ["pets_0_name"]=>
  string(6) "snooop"
        ["pets_1_id"]=>
  int(2)
  ["pets_1_name"]=>
  string(5) "medor"
        ["job_title"]=>
  string(10) "developper"
}

看到https://ideone.com/KXLtzZ stdout

非递归,非基于引用的实现,这可能比基于递归的实现更容易理解。 可以管理任意深度多维数组,不能平化关联数组。 它的工作原理是每个周期将数组压平一层,直到它完全有效。

function array_flatten(): array{
    $result = func_get_args();
    // check all elements of $list are not arrays
    $_is_flat = function (array $list): bool {
        foreach ($list as $val) {
            if (is_array($val)) {
                return false;
            }
        }
        return true;
    };
    do {
        $tmp = [];
        foreach ($result as $val) {
            if (is_array($val)) {
                if (!array_is_list($val)) {
                    throw new \Exception(sprintf("array_flatten can't handle associative arrays: %s", json_encode($val)));
                }
                $tmp = array_merge($tmp, $val);
            } else {
                $tmp[] = $val;
            }
        }
        $result = $tmp;
    } while (!$_is_flat($result));
    return $result;
}

以下是它处理的情况:

assertEquals(array_flatten(1, 2), $expected = [1, 2], 'array_flatten 1a');
assertEquals(array_flatten([1], [2]), $expected = [1, 2], 'array_flatten 1b');
assertEquals(array_flatten([1], [[2], 3]), $expected = [1, 2, 3], 'array_flatten 1c');
assertEquals(array_flatten(1, [2, 3], [4, 5]), $expected = [1, 2, 3, 4, 5], 'array_flatten 2');
assertEquals(array_flatten(2, 3, [4, 5], [6, 7], 8), $expected = [2, 3, 4, 5, 6, 7, 8], 'array_flatten 3');
assertEquals(array_flatten([2, 3, [4, 5], [6, 7], 8]), $expected = [2, 3, 4, 5, 6, 7, 8], 'array_flatten 4');
assertEquals(array_flatten([2, [3, [4, [5]], [6, [7]], 8]]), $expected = [2, 3, 4, 5, 6, 7, 8], 'array_flatten complex');

试试下面这个简单的函数:

function _flatten_array($arr) {
  while ($arr) {
    list($key, $value) = each($arr); 
    is_array($value) ? $arr = $value : $out[$key] = $value;
    unset($arr[$key]);
  }
  return (array)$out;
}

所以从这里:

array (
  'und' => 
  array (
    'profiles' => 
    array (
      0 => 
      array (
        'commerce_customer_address' => 
        array (
          'und' => 
          array (
            0 => 
            array (
              'first_name' => 'First name',
              'last_name' => 'Last name',
              'thoroughfare' => 'Address 1',
              'premise' => 'Address 2',
              'locality' => 'Town/City',
              'administrative_area' => 'County',
              'postal_code' => 'Postcode',
            ),
          ),
        ),
      ),
    ),
  ),
)

你会得到:

array (
  'first_name' => 'First name',
  'last_name' => 'Last name',
  'thoroughfare' => 'Address 1',
  'premise' => 'Address 2',
  'locality' => 'Town/City',
  'administrative_area' => 'County',
  'postal_code' => 'Postcode',
)