Home > Enterprise >  Flatten a 2d array while preserving numeric associative row keys
Flatten a 2d array while preserving numeric associative row keys

Time:01-14

I need to flatten a 2d array to become a 1d array without losing my numeric 2nd level keys in the process.

Sample data:

[
    [2015 => '2015'],
    [2016 => '2016'],
    [2017 => '2017'],
    [2018 => '2018'],
    [2019 => '2019'],
    [2020 => '2020'],
    [2021 => '2021'],
    [2022 => '2022'],
    [2023 => '2023']
]

Desired output:

[
    2015 => '2015',
    2016 => '2016',
    2017 => '2017',
    2018 => '2018',
    2019 => '2019',
    2020 => '2020',
    2021 => '2021',
    2022 => '2022',
    2023 => '2023'
]

Is it possible to get output like this?

CodePudding user response:

You could do simple foreach loop:

<?php

$years = array(
    array(2015 => '2015'),
    array(2016 => '2016'),
    array(2017 => '2017'),
    array(2018 => '2018'),
    array(2019 => '2019'),
    array(2020 => '2020'),
    array(2021 => '2021'),
    array(2022 => '2022'),
    array(2023 => '2023')
);

foreach($years as $year) {
    $key = key($year);
    $value = current($year);
    $result[$key] = $value;
}

var_dump($result);

Output:

$result = [
    2015 => '2015',
    2016 => '2016',
    2017 => '2017',
    2018 => '2018',
    2019 => '2019',
    2020 => '2020',
    2021 => '2021',
    2022 => '2022',
    2023 => '2023'
];

CodePudding user response:

$theArray = [ 
    [2020 => '2020'], [2021 => '2021'], [2022 => '2022'], [2023 => '2023'],
    [2015 => '2015'], [2016 => '2016'], [2017 => '2017'], [2018 => '2018'], [2019 => '2019']
];

$new = [];
foreach ( $theArray as $a) {
    $new[key($a)] = $a[key($a)];
}
ksort($new);
print_r($new);

RESULTS

Array
(
    [2015] => 2015
    [2016] => 2016
    [2017] => 2017
    [2018] => 2018
    [2019] => 2019
    [2020] => 2020
    [2021] => 2021
    [2022] => 2022
    [2023] => 2023
)

Of course, it might be more efficient to go to the code that created your original array and amend that to create what you want rather than what it currently does.

CodePudding user response:

I originally closed this page with this canonical page: How to Flatten a Multidimensional Array? After consulting with a moderator, it was advised that this question with narrower requirements should be reopened instead of clarifying the behavior of each answer on the other page which contains a mixture of viable and non-viable solutions for this question.

Here is a rather comprehensive list of viable techniques:


array_reduce() using the union operator with PHP7.4's arrow function syntax generates no variables in the global scope. (Demo)

var_export(
    array_reduce($array, fn($result, $row) => $result   $row, [])
);

array_reduce() using array_replace() with PHP7.4's arrow function syntax generates no variables in the global scope. (Demo)

var_export(
    array_reduce($array, fn($result, $row) => array_replace($result, $row), [])
);

Converting the data from recursive iterator methods to an array generates no variables in the global scope. Demo

var_export(
    iterator_to_array(new RecursiveIteratorIterator(new RecursiveArrayIterator($array)))
);

array_walk() requires a global variable to be declared and it is modified by reference in the closure and calls key(). Demo

$result = [];
array_walk($years, function($row) use(&$result) { $k = key($row); $result[$k] = $row[$k]; });
var_export($result);

array_walk_recursive() requires a global variable to be declared and it is modified by reference in the closure without calling key(). Demo

$result = [];
array_walk_recursive($years, function($v, $k) use (&$result) { $result[$k] = $v; });
var_export($result);

Nested foreach() loops generate multiple variables in the global scope, but call no functions. Demo

$result = [];
foreach ($array as $row) {
    foreach ($row as $k => $v) {
        $result[$k] = $v;
    }
}
var_export($result);

There are other viable approaches that use manually scripted recursion and generators but they are less attractive in terms of readability and are likely to be overkill for this task (in my opinion).


Now for the approaches that must not be used because they lose the numeric associative keys in the rows. DON'T use these flattening techniques for this question's data set / requirements.

Laravel's Arr::flatten() method implements manually written recursive code which returns a flat, indexed array -- not appropriate for this case.

Ouzo goodies's Array::flatten() method uses array_walk_recursive() to return an flat, indexed array -- not appropriate for this case.

  • Related