如何递归地将关联数组项复制到另一个单一数组项?

4
我有一个关联数组,其中的键是像软件发布版本号一样编号的,例如32.1。我想做的是将32.1之后的每个版本(32.2、32.3、32.4等)分配到另一个数组中,在32键下,更重要的是,我需要脚本递归执行,以便具有多个发行版的更长版本号最终出现在正确的数组键中。
我的代码...
<?php

    $array = array(
        '1' => 'Level 1',
        '1-1' => 'Level 1',
        '1-2' => 'Level 1',
        '1-2-1' => 'Sub-Level 1',
        '2' => 'Level 2',
        '3' => 'Level 3'
    );

    foreach ($array as $key => $value) {
        static $assoc = array();

        if (preg_match('/-/', $key)) {
            $points = explode('-', $key);
            $assoc_key = basename($key, '-' . end($points));
            $assoc[$assoc_key]['sub'][$key] = array('1' => 'Sub-' . $array[end($points)]);
        } else {
            $assoc[$key] = array('1' => $array[$key]);
        }
    }

    echo '<pre>' . print_r($assoc, true) . '</pre>';

?>

期望输出:

Array
(
  [1] => Array
    (
      [1] => Level 1
      [sub] => Array
        (
          [1-1] => Array
            (
              [1] => Sub-Level 1
            )

          [1-2] => Array
            (
              [1] => Sub-Level 2
              [sub] => Array
                (
                  [1-2-1] => Array
                    (
                      [1] => Sub-Sub-Level 1
                    )

                )

            )

        )

    )

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

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

)

实际输出

Array
(
  [1] => Array
    (
      [1] => Level 1
      [sub] => Array
        (
          [1-1] => Array
            (
              [1] => Sub-Level 1
            )

          [1-2] => Array
            (
              [1] => Sub-Level 2
            )

        )

    )

  [1-2] => Array
    (
      [sub] => Array
        (
          [1-2-1] => Array
            (
              [1] => Sub-Level 1
            )

        )

    )

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

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

)

有人可以帮忙吗?

我知道我错过了什么简单的东西,但是我已经尝试了两天,还是无法让它工作。


也许这是一个重复的问题 - halfer
你确定你的输入数组是正确的吗?1-1和1-2不应该是子级别1和1-2-1子子级别1吗? - mTorres
halfer:不,它不是。这个问题是关于在一个数组中使用相似的键添加项目到另一个数组中的单数键下,以便将它们“分组”。 - Coffee'd Up Hacker
mTorres:那部分并不是很重要,但是每个“子”项目中的“级别”数字应该重新从“1”开始。 - Coffee'd Up Hacker
2个回答

2
我想到了一些可以使用数组引用解决您问题的方法。可能代码还可以进一步优化,但应该足以展示概念。正如您所述,函数必须是递归的,但您使用了迭代的方法。
<?php
  $array = array(
    '1' => 'Level 1',
    '1-1' => 'Level 1',
    '1-2' => 'Level 1.2',
    '1-2-1' => 'Level 1.2.1',
    '2' => 'Level 2',
    '3' => 'Level 3'
  );

  $assoc = array();

  foreach ($array as $key => $value) {
    if (strpos($key, "-") !== false) {
      $points  = explode('-', $key);
      $current = &$assoc[$points[0]];
      $str     = $points[0];
      for ($i = 1; $i < count($points); $i++) {
        $str    .= "-" . $points[$i];
        if (!isset($current["sub"]))
          $current["sub"] = array();
        $current = &$current["sub"][$str];
      }
      $current[1] = 'Sub-' . $value;
    }
    else {
      $assoc[$key][1] = $array[$key];
    }
  }


  echo '<pre>' . print_r($assoc, true) . '</pre>';
?>

经过多次测试,我发现这是一个完美的解决方案。谢谢! - Coffee'd Up Hacker

0
**编辑:**你之所以得到这种结果,是因为在构建$assoc_key时,如果你得到的是$assoc_key='1-2',那么你不应该构建$assoc[$assoc_key]['sub'][$key] = array('1' => 'Sub-' . $array[end($points)]);,因为它会创建一个基于id为'1-2'的新数组,你应该创建$assoc[$pre_asscokey]['sub'][$assoc_key][$key] = array('1' => 'Sub-' . $array[end($points)]);,所以试试这个方法:
   <?php

    $array = array(
        '1' => 'Level 1',
        '1-1' => 'Level 1',
        '1-2' => 'Level 1',
        '1-2-1' => 'Sub-Level 1',
        '2' => 'Level 2',
        '3' => 'Level 3'
    );
    static $assoc = array();
    foreach ($array as $key => $value) {


        if (preg_match('/-/', $key)) {
            $points = explode('-', $key);
            $assoc_key = basename($key, '-' . end($points)); 
            $x=$points[0];
            if($assoc_key == $pre_asscokey  && sizeof($points)==3){
          $assoc[$x]['sub'][$pre_asscokey]['sub'][$key] = array('1' => 'Sub-' . $array[end($points)]);
            }else{
            $assoc[$assoc_key]['sub'][$key] = array('1' => 'Sub-' . $array[end($points)]);
         $pre_asscokey = $key;
            }
        } else {
            $assoc[$key] = array('1' => $array[$key]);
            $pre_asscokey=$key;
        }
    }

    echo '<pre>' . print_r($assoc, true) . '</pre>';

?>

输出:

Array
(
    [1] => Array
        (
            [1] => Level 1
            [sub] => Array
                (
                    [1-1] => Array
                        (
                            [1] => Sub-Level 1
                        )

                    [1-2] => Array
                        (
                            [1] => Sub-Level 2
                            [sub] => Array
                                (
                                    [1-2-1] => Array
                                        (
                                            [1] => Sub-Level 1
                                        )

                                )

                        )

                )

        )

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

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

)

我之前尝试过这种方法,但它也是错误的,因为$array['1-2-1']最终会被放入$assoc['1']['sub']中,而实际上应该放入$assoc['1']['sub']['1']['1-2']中等等。 - Coffee'd Up Hacker
suchit:我现在已经测试过了,它不是递归的,它只能处理最多两个级别。这就是我发现很难解决的问题。 - Coffee'd Up Hacker

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接