穿越&在多维php数组中更改子键

时间:2011-09-29 19:18:08

标签: php arrays multidimensional-array

我有一个多维数组,如下所示:

Array(
  [135] => Array(
    [150] => Array(
      [151] => Array(
        [1]   => Array()
        [153] => Array()
      )
      [1] => Array(
        [1] => Array()
        [2] => Array()
      )
    )
    [1] => Array(
      [1] => Array(
        [1] => Array()
        [2] => Array()
      )
      [2] => Array(
        [1] => Array()
        [2] => Array()
      )
    )
  )
)

我想更改为以下内容:

Array(
  [135] => Array(
    [150|135] => Array(
      [151|150] => Array(
        [1|151]   => Array()
        [153|151] => Array()
      )
      [1|150] => Array(
        [1|1] => Array()
        [2|1] => Array()
      )
    )
    [1|135] => Array(
      [1|1] => Array(
        [1|1] => Array()
        [2|1] => Array()
      )
      [2|1] => Array(
        [1|2] => Array()
        [2|2] => Array()
      )
    )
  )
)

我的意思是每个子键都有his key | parent key格式。树标签是固定的。没有比上面代码中显示的更深或更少的深度。

最好的方法是什么?感谢您的帮助

3 个答案:

答案 0 :(得分:0)

试试这个:

    $arr = Array ( [135] => Array ( [150] => Array ( [151] => Array ( [1] => Array ( )))));

foreach($arr as $key1 => $value1)
{
    if(is_array($value1))
    {
        foreach($value1 as $key2 => $value2)
        {
            if(is_array($value2))
            {
                  foreach($value2 as $key3 => $value3)
                  {
                      if(is_array($value3))
                      {
                          foreach($value3 as $key4 => $value4)
                          {
                              if(is_array($value4))
                              {
                                   foreach($value4 as $key5 => $value5)
                                   {
                                        $value4[$key5.'|'.$key4] = $value5;
                                        unset($value4[$key5]);
                                   }
                              }
                              else
                              {
                                   $value3[$key4.'|'.$key3] = $value4;
                                   unset($value3[$key4]);
                              }
                          }                          
                       }
                       else
                       {
                           $value2[$key3.'|'.$key2] = $value3;
                           unset($value2[$key3]);
                       }
                  }
            }
            else
            {
                 $value1[$key2.'|'.$key1] = $value2;
                 unset($value1[$key2]);
            }
        }
    }
}

我认为这可以给你一些想法,但我没有测试过,所以我不确定正确性。

答案 1 :(得分:0)

不需要疯狂的嵌套foreach()循环来解决这个问题。递归是你的朋友:

function get_fancy_array($arr, $parent_id=null) {
  $fancy_arr = array();

  // turn e.g. 'parent' or 'parent|child' into '|parent' and NULL into ''
  $parent_id_sufx = $parent_id === null ?
    '' : '|' . explode('|', (strint)$parent_id, 1)[0];

  foreach($arr as $key => $val) {
    $key = (string)$key . $parent_id_sufx;

    if( is_array($val) ) {
      // it's an array, so recursively do the same thing at the next level
      $fancy_array[$key] = get_fancy_arr($val, $key);
    } else {
      $fancy_array[$key] = $val;
    }
  }

  return $fancy_arr;
}

// Usage:
$arr = array( /* your big nested array here */ );

$fancier_arr = get_fancy_array($arr);
print_r($fancier_arr);

答案 2 :(得分:0)

你可以像你问的那样:遍历和更改密钥(Demo):

/**
 * traverse array and
 * add parent key to children key
 * 
 * @param array $a (return)
 * @param int $p (optional) parent key 
 */
function changeKeys(array &$a, $p = null)
{
    static $f = __FUNCTION__;

    foreach($a as $k => &$v)
    {
        # test if already processed
        if (is_string($k))
            return;

        # traverse children if children exists
        if ($v)
            $f($v, $k);        

        # rename key if parent exists
        if ($p)
        {
            $a["$k|$p"] = &$v;            
            unset($a[$k]);
        }
    }
}

此函数遍历递归(函数调用自身),因此它可以在多个级别上运行。

实际上不可能更改数组键,不存在array_rename_key之类的功能。而是添加具有新密钥的项目,然后删除具有旧密钥的项目。为了不重复值,在上面的示例中使用了引用/别名:

$a["$k|$p"] = &$v;            
unset($a[$k]);

$a是数组,$v是当前元素的值,$k是键,$p是父键。

当在数组的末尾添加新元素时,在foreach内部需要检查是否已经处理了一个密钥(它是一个新密钥,所有新密钥都是字符串)。