繁体   English   中英

在多维php数组中遍历和更改子键

[英]Traversing & changing child key in a multidimentional php 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 his key | parent key格式。 树标签是固定的。 深度不得超过上述代码中所示的深度。

做这个的最好方式是什么? 感谢您的协助

尝试这个:

    $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]);
            }
        }
    }
}

我认为这可以给您一些想法,但我尚未对此进行测试,因此我对正确性不是很确定。

不需要疯狂的嵌套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);

您可以按照要求进行操作:遍历和更改键( 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内部需要检查是否已处理键(这是一个新键,所有新键都是字符串),以退出。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM