简体   繁体   中英

PHP RecursiveIteratorIterator overwrites array keys

Here is the function I wrote to flatten the multidimensional PHP array:

function flattenArray(array $array) {
    if (! is_array($array)) {
        throw new Exception ("Please specify an array.");
    }

    $resultArray = [];
    $arrayObject = new RecursiveArrayIterator($array);

    foreach(new RecursiveIteratorIterator($arrayObject) as $key => $value) {
        $resultArray[$key] = $value;
    }

    return $resultArray;
}

And using it:

$arr = [
    ["sitepoint", "phpmaster"],
    ["buildmobile", "rubysource"],
    ["designfestival", "cloudspring"],
    "not an array"
];

print_r(flattenArray($arr));

Result:

Array
(
    [0] => designfestival
    [1] => cloudspring
    [3] => not an array
)

However, I was expecting:

0: sitepoint
1: phpmaster
2: buildmobile
3: rubysource
4: designfestival
5: cloudspring
6: not an array

But it is re-generating indexes as in:

0: sitepoint
1: phpmaster
0: buildmobile
1: rubysource
0: designfestival
1: cloudspring
3: not an array

So how do I modify function to get all elements of the array not just three:

Array
(
    [0] => designfestival
    [1] => cloudspring
    [3] => not an array
)

Thanks for the help

  1. if (!is_array($array)) is superfluous, since you have the array type hint in the function signature and PHP will enforce that.
  2. You are overwriting the keys. Those elements all have the same keys in their respective subarray. Since it's not an associative array, you don't need to preserve the keys. Instead of

     $resultArray[$key] = $value; 

    just do

     $resultArray[] = $value; 

I too hit this limitation with RecursiveIteratorIterator.

At first I had been using this concise, one-line array flattener wherever needed:

$outputs = iterator_to_array(new \RecursiveIteratorIterator(new \RecursiveArrayIterator([$inputs])), FALSE);

similar to your longer function above.

All was great: I was able to "normalize" my data structure into a 1D array, no matter if the incoming $inputs parameter came into my Symfony2 Controller as a single String/float value, 1D or 2+D multidimensional array. (I was writing a callback from AJAX that is to respond with JSON-formatted tables for an interactive Highcharts.com chart to be able to render, in my financial app.)

However, it refused to draw because in the final step, each data cell was in the form

 0 => float 100.662 

even though I had taken care that my $inputs creature only contained cells in the form:

 '2002-04-30' => float 100.662

So basically the above array-flattening line had killed the keys (DateStamp).

Fed up with studying RecursiveIteratorIterator, I just broke down and came up with my own array_flatten that preserves keys, if any :

static public function array_flatten($inObj)
  {
    $outObj = [];  $inObj=[$inObj];
    array_walk_recursive($inObj, function ($incell, $inkey) use (&$outObj) 
        {
        $outObj[$inkey] = $incell;
        }  );
    return $outObj;
  }

Note that you are responsible for ensuring that the keys in $inObj are globally unique (and either string or int type), otherwise, I don't know how my function behaves. Probably overwrites the value using the same key name?

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM