如何减少5级深度数组的嵌套foreach

时间:2019-05-10 08:06:02

标签: php arrays foreach tree-traversal

我有一个PHP树形结构(数组最大深度:5):

$arr = array(
    '31' => array(
        'Amsterdam' => array(),
        'Rotterdam' => array(),
        'Den Haag' => array(),
        'Utrecht' => array(),
        'Eindhoven' => array(),
        'Tilburg' => array(),
        'Almere' => array(
            '036' => array(
                'BU00340212' => array(
                    'name' => 'Muziekwijk Noord',
                    'residents' => array(
                        'Henk',
                        'Dirk',
                        'Jaap',
                    ),
                ),
                'BU00340213' => array(
                    'name' => 'Muziekwijk Zuid',
                    'residents' => array(
                        'Wim',
                        'Pim',
                        'Jim',
                        'Tim',
                    ),
                ),
            )
        ),
        'Groningen' => array(),
        'Breda' => array(),
        'Nijmegen' => array(),
    )
);

我想要这个输出:

Almere(netnummer: 036)(cbscode: BU00340212): Henk
Almere(netnummer: 036)(cbscode: BU00340212): Dirk
Almere(netnummer: 036)(cbscode: BU00340212): Jaap
Almere(netnummer: 036)(cbscode: BU00340213): Wim
Almere(netnummer: 036)(cbscode: BU00340213): Pim
Almere(netnummer: 036)(cbscode: BU00340213): Jim
Almere(netnummer: 036)(cbscode: BU00340213): Tim

所以我自己做了一些编码。下面的代码产生我想要的输出。

foreach($arr as $unitKey => $citySet){

    foreach($citySet as $cityName => $cityData){

        if($cityName === 'Almere'){

            $almere = $citySet[$cityName];

            foreach($almere as $netnummer => $netData){

                foreach($netData as $cbsCode => $data){

                    foreach($data['residents'] as $residents){
                        echo $cityName . '(netnummer: '. $netnummer .')(cbscode: '. $cbsCode .'): ' . $residents . '<br>';
                    }
                }
            }
        }
    }
}

上面显示的代码使用了5个foreach,我怀疑这是否是个好主意。因此,我尝试减少这样的几个foreach:

$arrB = $arr['31']['Almere']['036'];
foreach($arrB as $k => $netData){
    foreach($netData as $field => $fieldData){
        if($field === 'residents') {
            foreach($fieldData as $resident){
                echo 'Almere(netnummer: 036)(cbscode: '. $k .'): ' . $resident . '<br>';
            }
        }
    }
}

上面显示的代码使用3个foreach。那是因为它没有遍历整个树。

我想遍历整棵树,每棵树有1个foreach,并产生我想要的输出。所以我在考虑将RecursiveArray与RecursiveIteratorIterator结合使用,但是如果使用这种方法,我将无法获得cbscode。亲自看看:

$recursiveArrayIterator = new RecursiveArrayIterator($arr);
$recursiveIteratorIterator = new RecursiveIteratorIterator($recursiveArrayIterator);
foreach($recursiveIteratorIterator as $k => $v){
    if($k !== 'name'){
        echo 'Almere(netnummer: 036)(cbscode: ???): ' . $v . '<br>';
    }
}

Q1:是否可以通过显示输出的一个foreach遍历树结构?

Q2:如果可以,您可以显示代码吗?如果没有,是否有可能将foreach的使用量减少到2个?

-编辑-

问(改写):完全遍历5级深度数组最可读的方法是什么?

2 个答案:

答案 0 :(得分:4)

您可以将其简化为:

$arrB = $arr['31']['Almere']['036'];
foreach($arrB as $code => $val) {
    if (isset($val["residents"])) {
        $prefix = 'Almere(netnummer: 036)(cbscode: '. $code .'): ';
        echo $prefix . implode('<br>' . $prefix, $val["residents"]) . '<br>';
    }
}

实时示例:3v4l

答案 1 :(得分:1)

我花了一些时间解决这个问题,并提供了一种函数式编程方法:

function recursive($data, $countryCode = null, $countryData = null, $city = null, $cityData = null, $netNummer = null, $netData = null, $cbscode = null, $cbsData = null, $residents = null){

    if($residents){
        $resident = array_shift($residents);
        echo $city . '(netnummer: ' . $netNummer . ')(cbscode: ' . $cbscode .'): ' . $resident . '<br>';

        if($residents){
            recursive($data, $countryCode, $countryData, $city, $cityData, $netNummer, $netData, $cbscode, $cbsData, $residents);
        }

        return null;
    }

    if($cbscode && $cbsData){
        $residents = $cbsData['residents'];
        recursive($data, $countryCode, $countryData, $city, $cityData, $netNummer, $netData, $cbscode, $cbsData, $residents);
    }

    if($countryCode && $countryData && $netData){
        $cbscode = key($netData);
        $cbsData = array_shift($netData);
        recursive($data, $countryCode, $countryData, $city, $cityData, $netNummer, $netData, $cbscode, $cbsData);
    }

    if($countryCode && $countryData && $city && $cityData){
        $netNummer = key($cityData);
        $netData = array_shift($cityData);
        recursive($data, $countryCode, $countryData, $city, $cityData, $netNummer, $netData);
    }

    if($countryCode && $countryData){
        $city = key($countryData);
        $cityData = array_shift($countryData);
        recursive($data, $countryCode, $countryData, $city, $cityData);
    }

    if($data){
        $countryCode = key($data);
        $countryData = array_shift($data);
        if($countryData){
            recursive($data, $countryCode, $countryData);
        }
    }

    return null;
}

recursive($arr);

在线来源:https://3v4l.org/rsf5o