PHP 遍历多维数组同时保留键

发布于 2024-12-11 09:45:28 字数 562 浏览 0 评论 0原文

我有一个多维数组,我不知道其深度。例如,该数组可能如下所示:

$array = array(
    1 => array(
        5 => array(
            3 => 'testvalue1'
        )
    ),
    2 => array(
        6 => 'testvalue2'
    ),
    3 => 'testvalue3',
    4 => 'testvalue4',
);

我想使用该数组创建一个目录。这意味着需要保留密钥,因为我将它们用作“章节编号”。例如,“testvalue1”位于第 1.5.3 章中。
现在我想遍历数组,同时保留所有键 - 不使用 array_walk_recursive,因为包含另一个数组的键被删除(正确?),考虑到速度,最好不使用嵌套的 foreach 循环。
有什么建议我应该如何做到这一点?提前致谢。

PS:对于我的脚本来说,键是字符串(“1”而不是 1)还是整数并不重要,如果将字符串作为键将使 array_walk_recursive 保留它们。

I've got a multidimensional array of which I can't know the depth. The array could for example look like this:

$array = array(
    1 => array(
        5 => array(
            3 => 'testvalue1'
        )
    ),
    2 => array(
        6 => 'testvalue2'
    ),
    3 => 'testvalue3',
    4 => 'testvalue4',
);

With this array I want to create a table of contents. That means the keys need to be preserved as I'm using them as "chapter numbers". For example, "testvalue1" is in chapter 1.5.3.
Now I want to walk through the array while preserving all keys - not using array_walk_recursive as the keys containing another array are dropped (correct?) and preferably not using nested foreach loops considering the speed.
Any suggestions how I should do this? Thanks in advance.

PS: For my script it doesn't matter if the keys are strings ("1" instead of 1) or integers, if having strings as key will make array_walk_recursive preserve them.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

和我恋爱吧 2024-12-18 09:45:28

您可以借助堆栈迭代数组来构建目录。

$stack = &$array;
$separator = '.';
$toc = array();

while ($stack) {
    list($key, $value) = each($stack);
    unset($stack[$key]);
    if (is_array($value)) {
        $build = array($key => ''); # numbering without a title.
        foreach ($value as $subKey => $node)
            $build[$key . $separator . $subKey] = $node;
        $stack = $build + $stack;
        continue;
    }
    $toc[$key] = $key. ' ' . $value;
}

print_r($toc);

输出:

Array
(
    [1] => 1
    [1.5] => 1.5
    [1.5.3] => 1.5.3 testvalue1
    [2] => 2
    [2.6] => 2.6 testvalue2
    [3] => 3 testvalue3
    [4] => 4 testvalue4
)

如果需要,您也可以另外处理该级别,但这从您的问题中并不清楚。

array_walk_recursive 不起作用,因为它不会为您提供父元素的键。另请参阅此相关问题:Transparently flatten an array,它有一个很好的答案并且对于更一般的情况也很有帮助。

You can iterate over your array with a help of a stack to build your toc.

$stack = &$array;
$separator = '.';
$toc = array();

while ($stack) {
    list($key, $value) = each($stack);
    unset($stack[$key]);
    if (is_array($value)) {
        $build = array($key => ''); # numbering without a title.
        foreach ($value as $subKey => $node)
            $build[$key . $separator . $subKey] = $node;
        $stack = $build + $stack;
        continue;
    }
    $toc[$key] = $key. ' ' . $value;
}

print_r($toc);

Output:

Array
(
    [1] => 1
    [1.5] => 1.5
    [1.5.3] => 1.5.3 testvalue1
    [2] => 2
    [2.6] => 2.6 testvalue2
    [3] => 3 testvalue3
    [4] => 4 testvalue4
)

You can additionally handle the level as well if you need to, but that was not clear from your question.

array_walk_recursive does not work, because it won't give you the keys of the parent element(s). See this related question as well: Transparently flatten an array, it has a good answer and is helpful for more generic cases as well.

兔姬 2024-12-18 09:45:28
<?php
    $td = array(1=>array(5=>array(3=>'testvalue1',array(6=>'testvalue2'))),2=>array(6=>'testvalue2',array(6=>'testvalue2',array(6=>'testvalue2'),array(6=>'testvalue2',array(6=>'testvalue2')))),3=>'testvalue3',4=>'testvalue4');
    print_r($td);
    $toc = '';

    function TOC($arr,$ke='',$l=array()) {
            if (is_array($arr)) {
            if ($ke != '') array_push($l,$ke);
            foreach($arr as $k => $v)
                TOC($v,$k,$l);
        }
        else {
            array_push($l,$ke);
            $GLOBALS['toc'].=implode('.',$l)." = $arr\n";
        }
    }
    toc($td);
    echo "\n\n".$toc;
?>

http://codepad.org/4l4385MZ

<?php
    $td = array(1=>array(5=>array(3=>'testvalue1',array(6=>'testvalue2'))),2=>array(6=>'testvalue2',array(6=>'testvalue2',array(6=>'testvalue2'),array(6=>'testvalue2',array(6=>'testvalue2')))),3=>'testvalue3',4=>'testvalue4');
    print_r($td);
    $toc = '';

    function TOC($arr,$ke='',$l=array()) {
            if (is_array($arr)) {
            if ($ke != '') array_push($l,$ke);
            foreach($arr as $k => $v)
                TOC($v,$k,$l);
        }
        else {
            array_push($l,$ke);
            $GLOBALS['toc'].=implode('.',$l)." = $arr\n";
        }
    }
    toc($td);
    echo "\n\n".$toc;
?>

http://codepad.org/4l4385MZ

梦晓ヶ微光ヅ倾城 2024-12-18 09:45:28

试试这个:

<?php
$ar = array(
    1 => array(
        5 => array(
            3 => 'testvalue1',
            5 => 'test',
            6 => array(
                9 => 'testval 9'
            )
        ),
        8 => 'testvalue9'
    ),
    2 => array(
        6 => 'testvalue2',
        7 => 'testvalue8',
        2 => array(
            6 => 'testvalue2',
            7 => 'testvalue8'
        ),
    ),
    3 => 'testvalue3',
    4 => 'testvalue4'
);

function getNestedItems($input, $level = array()){
    $output = array();

    foreach($input as $key => $item){
        $level[] = $key;
        if(is_array($item)){
            $output = (array)$output + (array)getNestedItems($item, $level);
        } else {
            $output[(string)implode('.', $level)] = $item;
        }
        array_pop($level);
     }
     return $output;
}

var_dump(getNestedItems($ar));

Try this:

<?php
$ar = array(
    1 => array(
        5 => array(
            3 => 'testvalue1',
            5 => 'test',
            6 => array(
                9 => 'testval 9'
            )
        ),
        8 => 'testvalue9'
    ),
    2 => array(
        6 => 'testvalue2',
        7 => 'testvalue8',
        2 => array(
            6 => 'testvalue2',
            7 => 'testvalue8'
        ),
    ),
    3 => 'testvalue3',
    4 => 'testvalue4'
);

function getNestedItems($input, $level = array()){
    $output = array();

    foreach($input as $key => $item){
        $level[] = $key;
        if(is_array($item)){
            $output = (array)$output + (array)getNestedItems($item, $level);
        } else {
            $output[(string)implode('.', $level)] = $item;
        }
        array_pop($level);
     }
     return $output;
}

var_dump(getNestedItems($ar));
°如果伤别离去 2024-12-18 09:45:28

另一种最适合我处理深层嵌套多维关联和非关联数组的方法:

/**
 * Flatten a Multidimensional Array
 */
function array_multidimensional_flatten( $array, $position = [], $separator = '.' ) {
  if ( !is_array( $array ) ) {
    return false;
  }

  $result = [];

  foreach ( $array as $key => $value ) {
    if ( is_array( $value ) ) {
      $position[] = $key;
      $result = array_merge( $result, array_multidimensional_flatten( $value, $position ) );
    } else {
      if ( $position ) {
        $key = implode( $separator, $position ) . "{$separator}{$key}";
      }
      $result = array_merge( $result, [$key => $value] );
    }
  }

  return $result;
}

将其与大型多维数组一起使用将输出如下内容:

[
  'hero__overlay-opacity' => '100',
  'hero__lead-in' => 'Underwritten by TruStage® Insurance',
  'hero__optimize' => '1',
  'hero__layout' => 'centered',
  'flexible-content.0.acf_fc_layout' => 'title',
  'flexible-content.0.acfe_flexible_toggle' => '',
  'flexible-content.0.text' => 'Enabling Smart Financial Decisions',
  'flexible-content.0.size.value' => 'lg',
  'flexible-content.0.size.label' => 'L',
  'flexible-content.0.size.alignment.value' => 'center',
  'flexible-content.0.size.alignment.label' => 'Center',
  'flexible-content.0.size.alignment.weight.value' => 'normal',
  'flexible-content.0.size.alignment.weight.label' => 'Regular',
  'flexible-content.0.1.acf_fc_layout' => 'grid-stats',
  'flexible-content.0.1.acfe_flexible_toggle' => '',
  'flexible-content.0.1.columns.0.statistic' => '85+',
  'flexible-content.0.1.columns.0.description' => 'Years of Experience',
  'flexible-content.0.1.columns.0.1.statistic' => 'A',
  'flexible-content.0.1.columns.0.1.description' => 'Financial rating1',
  'flexible-content.0.1.columns.0.1.2.statistic' => '4.75 / 5',
  'flexible-content.0.1.columns.0.1.2.description' => 'Rating on TrustPilot',
  'flexible-content.0.1.2.acf_fc_layout' => 'icon-columns',
  'flexible-content.0.1.2.acfe_flexible_toggle' => '',
  'flexible-content.0.1.2.title' => 'Insurance Products',
  'flexible-content.0.1.2.background' => 'rgb(246,246,246)',
  'flexible-content.0.1.2.alignment.value' => 'center',
  'flexible-content.0.1.2.alignment.label' => 'Center',
  'flexible-content.0.1.2.alignment.style.value' => 'default',
  'flexible-content.0.1.2.alignment.style.label' => 'Bordered Circle',
  'flexible-content.0.1.2.alignment.style.column.0.icon_type' => 'icon',
  'flexible-content.0.1.2.alignment.style.column.0.icon' => 'insurance-add',
  'flexible-content.0.1.2.alignment.style.column.0.image' => '',
  'flexible-content.0.1.2.alignment.style.column.0.title' => 'AD&D Insurance',
  'flexible-content.0.1.2.alignment.style.column.0.link' => '/insurance/accidental-death-dismemberment/',
]

Another take on this that worked best for me with handling deep nested multidimensional associative and non-associative arrays:

/**
 * Flatten a Multidimensional Array
 */
function array_multidimensional_flatten( $array, $position = [], $separator = '.' ) {
  if ( !is_array( $array ) ) {
    return false;
  }

  $result = [];

  foreach ( $array as $key => $value ) {
    if ( is_array( $value ) ) {
      $position[] = $key;
      $result = array_merge( $result, array_multidimensional_flatten( $value, $position ) );
    } else {
      if ( $position ) {
        $key = implode( $separator, $position ) . "{$separator}{$key}";
      }
      $result = array_merge( $result, [$key => $value] );
    }
  }

  return $result;
}

Using it with a large multidimensional array will output something like this:

[
  'hero__overlay-opacity' => '100',
  'hero__lead-in' => 'Underwritten by TruStage® Insurance',
  'hero__optimize' => '1',
  'hero__layout' => 'centered',
  'flexible-content.0.acf_fc_layout' => 'title',
  'flexible-content.0.acfe_flexible_toggle' => '',
  'flexible-content.0.text' => 'Enabling Smart Financial Decisions',
  'flexible-content.0.size.value' => 'lg',
  'flexible-content.0.size.label' => 'L',
  'flexible-content.0.size.alignment.value' => 'center',
  'flexible-content.0.size.alignment.label' => 'Center',
  'flexible-content.0.size.alignment.weight.value' => 'normal',
  'flexible-content.0.size.alignment.weight.label' => 'Regular',
  'flexible-content.0.1.acf_fc_layout' => 'grid-stats',
  'flexible-content.0.1.acfe_flexible_toggle' => '',
  'flexible-content.0.1.columns.0.statistic' => '85+',
  'flexible-content.0.1.columns.0.description' => 'Years of Experience',
  'flexible-content.0.1.columns.0.1.statistic' => 'A',
  'flexible-content.0.1.columns.0.1.description' => 'Financial rating1',
  'flexible-content.0.1.columns.0.1.2.statistic' => '4.75 / 5',
  'flexible-content.0.1.columns.0.1.2.description' => 'Rating on TrustPilot',
  'flexible-content.0.1.2.acf_fc_layout' => 'icon-columns',
  'flexible-content.0.1.2.acfe_flexible_toggle' => '',
  'flexible-content.0.1.2.title' => 'Insurance Products',
  'flexible-content.0.1.2.background' => 'rgb(246,246,246)',
  'flexible-content.0.1.2.alignment.value' => 'center',
  'flexible-content.0.1.2.alignment.label' => 'Center',
  'flexible-content.0.1.2.alignment.style.value' => 'default',
  'flexible-content.0.1.2.alignment.style.label' => 'Bordered Circle',
  'flexible-content.0.1.2.alignment.style.column.0.icon_type' => 'icon',
  'flexible-content.0.1.2.alignment.style.column.0.icon' => 'insurance-add',
  'flexible-content.0.1.2.alignment.style.column.0.image' => '',
  'flexible-content.0.1.2.alignment.style.column.0.title' => 'AD&D Insurance',
  'flexible-content.0.1.2.alignment.style.column.0.link' => '/insurance/accidental-death-dismemberment/',
]
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文