Flatten Array: Keep index, value equal to position

2019-07-03 22:09发布

问题:

I've been having a little trouble trying to flatten arrays in a specific way.

Here is a print_r view of the array I want to flatten:

Array
    (
        [1] => Array
            (
                [8] => 1
                [9] => 2
                [10] => Array
                    (
                        [15] => Array
                            (
                                [22] => 1
                            )

                        [21] => 2
                    )

                [11] => Array
                    (
                        [16] => Array
                            (
                                [23] => 1
                            )

                    )

            )

        [2] => Array
            (
                [12] => 1
            )

        [3] => Array
            (
                [13] => 1
            )

        [4] => Array
            (
                [14] => 1
            )

        [5] => 5
        [6] => 6
        [7] => 7
    )

What I'm attempting to create is an array which keeps the above indexes, but the value is equal to it's position in the array, much like the original index (starting from zero).

Here is the desired result:

Array
    (
        [1] => 1
        [2] => 2
        [3] => 3
        [4] => 4
        [5] => 5
        [6] => 6
        [7] => 7
        [8] => 1
        [9] => 2
        [10] => 3
        [11] => 4
        [12] => 1
        [13] => 1
        [14] => 1
        [15] => 1
        [16] => 1
        [21] => 2
        [22] => 2
        [23] => 1
    )

Knowingly, 17 to 20 are missing.

My function is as follows:

function array_flatten ($array) {
    $result                 = array ();
    $count                  = 1;
    while ($index = current($array)) {
        $result[key($array)] = $count;
        if (is_array($index)) {
            $result = array_merge(array_flatten($index), $result);
        }
        next($array);
        $count++;
    }
    return $result;
}

The line $result = array_merge(array_flatten($index), $result); appears to be the problems. It returns:

Array
(
    [1] => 1
    [2] => 2
    [3] => 3
    [4] => 4
    [5] => 5
    [6] => 6
    [7] => 7
)

However, if I run var_dump(array_flatten($index)); on the same line, it returns all the arrays I wish to merge to the $result variable.

array
  22 => int 1
array
  15 => int 1
  21 => int 2
array
  23 => int 1
array
  16 => int 1
array
  8 => int 1
  9 => int 2
  10 => int 3
  11 => int 4
array
  12 => int 1
array
  13 => int 1
array
  14 => int 1

It seems that that array_merge doesn't actually merge these arrays.

Is there something I am doing wrong? Any words of guidance are very much appreciated. Thank you.

Update

Solved!

The function which does the required is as follows:

function array_flatten($array, &$result = array()) {
    $count              = 1;
    foreach($array as $index => $value) {
        $result[$index] = $count;
        if(is_array($value)) {
            array_flatten($value, $result);
        }
        $count++;
    }
    return $result;
}

回答1:

function flatten_array($array, &$result) {
    foreach($array as $key => $value) {
        if(is_array($value)) {
            flatten_array($value, $result);
        } else {
            $result[$key] = $value;
        }
    }
}

To use this, check the sample code below:

$flattened = array();
$test = array(
      1 => 1
    , 3 => 2
    , array(2 => 4, 4 => 6)
    , 5 => 3
    , array(7 => 9, 8 => 7, 9 => 5)
);
flatten_array($test, $flattened);
// Now $flattened contains the flattened array


回答2:

After you have clarified your question, I was a bit surprised that you accepted an answer that does not return the data you expected. (I've now seen you added your solution to your question.)

What I did: I took the function from @Arjan as a base, and run it on the questions input data and compared it with the questions expected data. Then I worked on it a bit. This is what I came up with (as a result):

#   COMP  EXPECTED         . ACTUAL
#00:  ==  Array            . Array
#01:  ==  (                . (
#02:  ==      [1] => 1     .     [1] => 1
#03:  ==      [2] => 2     .     [2] => 2
#04:  ==      [3] => 3     .     [3] => 3
#05:  ==      [4] => 4     .     [4] => 4
#06:  ==      [5] => 5     .     [5] => 5
#07:  ==      [6] => 6     .     [6] => 6
#08:  ==      [7] => 7     .     [7] => 7
#09:  ==      [8] => 1     .     [8] => 1
#10:  ==      [9] => 2     .     [9] => 2
#11:  ==      [10] => 3    .     [10] => 3
#12:  ==      [11] => 4    .     [11] => 4
#13:  ==      [12] => 1    .     [12] => 1
#14:  ==      [13] => 1    .     [13] => 1
#15:  ==      [14] => 1    .     [14] => 1
#16:  ==      [15] => 1    .     [15] => 1
#17:  ==      [16] => 1    .     [16] => 1
#18:  ==      [21] => 2    .     [21] => 2
#19:  !=      [22] => 2    .     [22] => 1
#20:  ==      [23] => 1    .     [23] => 1
#21:  ==  )                . )
#22:  ==                   . 

It looks like that your expected data has a mistake for position 22.

This is the modified function (Demo):

function flatten_array($array, &$result = null) {
    $r = null === $result;
    $i = 0;
    foreach($array as $key => $value) {
        $i++;
        if(is_array($value)) {
            $result[$key] = $i;
            flatten_array($value, $result);
        } else {
            $result[$key] = $value;
        }
    }
    if ($r) {
        ksort($result);
        return $result;
    }
}

$actual = flatten_array($input);