【问题标题】:Generate multi-dimensional array from an array in php?从php中的数组生成多维数组?
【发布时间】:2022-01-17 10:28:24
【问题描述】:

我有一个关联数组列表如下:

[
"country" => "AU",
"state" => "VIC",
"suburb" => "Carlton",
"precedence" => ["country", "state", "suburb"]
]

我想要一个新的多维数组,如下所示,其中元素根据第一个数组上的 precedence 键定义的顺序嵌套:

[
 "country" => [
  "AU" => [
    "state" => [
      "VIC" => [
        "suburb" => "Carlton
      ]
     ]
    ]
   ]
]

以上只是一个示例,我想要一个适用于任何类型数组的通用解决方案。所有输入数组唯一满足的一个条件是它们将有一个 precedence 元素,表示需要生成输出数组的顺序。

我尝试了一些递归解决方案,但它没有按预期工作,并且出现 PHP 致命错误:允许的内存大小为 1073741824 字节已用尽(看起来它正在无限运行):

function generateArray(&$array)
    {
        foreach ($array['precedence'] as $key => $property) {
            if ($key == sizeof($array['precedence']) - 1) {
                return [$property => $array[$property]];
            } else {
                return generateAssetConfig($array);
            }
        }
    }

【问题讨论】:

  • 为什么需要制作这个结构?如果您需要 state 原样怎么办,如果它是这种结构,那么您将不知道它是键还是所有嵌套后的最终值。

标签: php arrays multidimensional-array


【解决方案1】:

您可以循环优先部分的反转项目。

如果结果数组中还没有项目,则添加第一个键 => 值对。

否则将当前结果包装在一个多维数组中,如果将迭代设置为外部键,则将当前值设置为,并将值(对于源数组中的该键)与当前结果一起包装在第二个数组中。

$source = [
    "country" => "AU",
    "state" => "VIC",
    "suburb" => "Carlton",
    "precedence" => ["country", "state", "suburb"]
];

function generateArray($array)
{
    $result = [];
    foreach(array_reverse($array["precedence"]) as $v) {
        $result =! $result ? [$v => $array[$v]] : [$v => [$array[$v] => $result]];
    }
    return $result;
}

var_export(generateArray($source));

输出

array (
  'country' => 
  array (
    'AU' => 
    array (
      'state' => 
      array (
        'VIC' => 
        array (
          'suburb' => 'Carlton',
        ),
      ),
    ),
  ),
)

【讨论】:

  • 谢谢大家!以下所有答案也是正确的,但我发现这个最简单,所以我投了赞成票。
  • 哇,很棒的解决方案!我什至无法考虑这一点。干得好!
【解决方案2】:

试试这个:

function generateNestedArray($arr) {
  $precedence = $arr['precedence'];
  $nestedArray = [];
  for ($i = count($precedence)-1; $i >= 0; $i--) {
    $key = $precedence[$i];
    if (!$nestedArray) {
      $nestedArray[$key] = $arr[$key];
    } else {
      $nestedArray = [$key => [ $arr[$key]=> $nestedArray]];
    }
  } 
  
  return $nestedArray;
}

【讨论】:

    【解决方案3】:

    这是一个递归算法:

    <?php
    
    $raw = [
        [
            "country" => "AU",
            "state" => "VIC",
            "suburb" => "Carlton",
            "precedence" => ["country", "state", "suburb"]
        ],
        [
            "country" => "AU",
            "state" => "NSW",
            "suburb" => "Sydney",
            "precedence" => ["country", "state", "suburb"]
        ]
    ];
    
    function generateFromPrecedence($array)
    {
        if (!isset($array['precedence']))
            throw new Exception('Precedence array does not exist');
    
        if (!empty(array_diff($array['precedence'], array_diff(array_keys($array), ['precedence']))))
            throw new Exception('Keys and precendence keys different');
    
        return generateStructure($array);
    }
    
    function generateStructure($array, $precedence = 0)
    {
        if ($precedence == count($array['precedence'])-1)
            return [$array['precedence'][$precedence] => $array[$array['precedence'][$precedence]]];
    
        return [$array['precedence'][$precedence] => [$array[$array['precedence'][$precedence]] => generateStructure($array, ++$precedence)]];
    }
    
    $output = generateFromPrecedence($raw[0]);
    
    var_dump($output);
    

    输出:

    array(1) {
    ["country"]=>
    array(1) {
        ["AU"]=>
        array(1) {
        ["state"]=>
        array(1) {
            ["NSW"]=>
            array(1) {
            ["suburb"]=>
            string(6) "Sydney"
            }
        }
        }
    }
    }
    

    【讨论】:

      【解决方案4】:

      最简单的解决方案(递归函数):

      function generateArrayRecursion($array, $precedenceIndex = 0) {
          $precedence = $array['precedence'];
          
          return [
              $precedence[$precedenceIndex] => $precedenceIndex === \count($precedence) - 1
                  ? $array[$precedence[$precedenceIndex]]
                  : [$array[$precedence[$precedenceIndex]] => generateArrayRecursion($array, $precedenceIndex + 1)]
          ];
      }
      

      替代解决方案(循环和数组引用):

      function generateArray($array) {
          $precedence = $array['precedence'];
          $result = [];
          $lastKey = $precedence[count($precedence) - 1];
      
          $currentElement = &$result;
          foreach ($precedence as $key) {
              if ($key === $lastKey) {
                  $currentElement[$key] = $array[$key];
              } else {
                  $currentElement[$key] = [$array[$key] => []];
                  $currentElement = &$currentElement[$key][$array[$key]];
              }
          }
          
          return $result;
      }
      

      用法示例:

      $array = [
          "country" => "AU",
          "state" => "VIC",
          "suburb" => "Carlton",
          "precedence" => ["country", "state", "suburb"]
      ];
      
      var_dump(generateArrayRecursion($array));
      var_dump(generateArray($array));
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2015-03-31
        • 2014-10-28
        • 2018-07-12
        • 1970-01-01
        • 1970-01-01
        • 2020-06-29
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多