按照数组键创建单独的子数组

3
我需要将一个单一的数组根据数组键中出现 > 的次数来分成子数组,以此来确定哪些是父类别,哪些不是。请注意,可能有无限多个嵌套的父级。
另外,如果存在同名的子项,则在具有不同父项的情况下被视为唯一。
我的源数组结构如下:
array (
  'Test Parent 2>Test Child>Test Sub Child' => 
  array (
    'content_id_4' => NULL,
  ),
  'Test Parent 3' => 
  array (
    'content_id_4' => NULL,
    'content_id_5' => NULL,
  ),
  'Test Parent>Test Child>Test Sub Child' => 
  array (
    'content_id_3' => NULL,
  ),
  'Test Parent 2 with No Kids' => 
  array (
    'content_id_3' => NULL,
  ),
  'Collections>Sports' => 
  array (
    'content_id_2' => NULL,
    'content_id_22' => NULL,
  ),
  'Collections' => 
  array (
    'content_id_2' => NULL,
    'content_id_22' => NULL,
    'content_id_6' => NULL,
  ),
  'Collections>Charity' => 
  array (
    'content_id_6' => NULL,
  ),
)

在上面的例子中,Test Parent>Test Child>Test Sub Child 意味着有一个名为 Test Parent 的父类别,其下有一个子类别 Test ChildTest Child 也是一个父类别,其下有一个名为 Test Sub Child 的子类别,它没有任何子类别。
array (
  'Collections' => 
  array (
    'Sports' => NULL,
    'Charity' => NULL,
  ),
  'Test Parent' => 
  array (
    'Test Child' => 
    array (
      'Test Sub Child' => NULL,
    ),
  ),
  'Test Parent 2 with No kids' => NULL,
  'Study' => 
  array (
    'Study Groups' => NULL,
  ),
)

我尝试了一个解决方案,但无法正确地获取语法,以便我可以创建一个具有子级孙子的额外数组。

我不一定需要重构我的示例。我只是在寻找最好的可行解决方案。

我的示例代码:

$category_structure = array();
foreach($event_categories as $main_cat => $content_ids) {

    $this_category_list = explode('>', $main_cat);

    $this_cat = array();
    $this_parent = array_shift($this_category_list);


    foreach($this_category_list as $cat) {
        $this_cat[$this_parent][$cat] = null;
    }

    $category_structure = array_merge_recursive($this_cat, $category_structure);


}

1
不要发布你的数组的 var_dump(),考虑发布它的 var_export() - nickb
@nickb - 已经注意并修复。 - Dave O'Dwyer
你能展示一下代码,这个数组是从哪里来的吗?肯定有什么方法可以让这个变得简单。@DaveO'Dwyer - viral
@Viral 源数组来自 CMS - 我无法控制其数据结构。 - Dave O'Dwyer
2个回答

2
这应该能为您工作,确保结果中没有零索引项。这来自于array_merge_recursive,通过将空值项与具有关联键的项合并来实现。虽然不如P0rnflake的解决方案优雅,但我相信您会明白的。
$collect = array();
$result = array();
$last = "";
foreach($event_categories as $main_cat => $content_ids) {
    if (strpos($last, $main_cat) === false) {
        array_push($collect, explode('>', $main_cat));
    }
    $last = $main_cat;
} 
array_walk($collect, function($value) use (&$result) {
    $out = array();
    $cur = &$out;
    foreach ($value as $array) {
        if (count($value) !== 1) {
            $cur[$array] = array();
        } else {
            $cur[$array] = null;    
        }
        $cur = &$cur[$array];
    }
    $cur = null;
    $result = array_merge_recursive($result, $out);
});
var_dump($result);

谢谢你,Dave。非常感激。这正如预期的一样运作良好。 - Dave O'Dwyer
当然,愉快地编码吧!;-) - DavidDomain

1
这个解决方案适用于 PHP 版本大于等于 5.3.0($yourArray 是输入数组):
// anonymous recursive function which merges a flat numeric array 
// into a hierarchy, f.e. array('parent','child','grandchild')
// will be built to a hierarchical array
$treeBuilder = function($numArray) use (&$treeBuilder) {
    if(isset($numArray[1])) {
        //recursive merge needed, there are still entries left
        return array(
            $numArray[0] => $treeBuilder(array_slice($numArray, 1))
        );
    }
    //end is reached
    return array(
        $numArray[0] => null
    );
};

$result = array();
foreach (array_keys($yourArray) as $key) {
    // loop through exploded keys and merge results
    $hierarchy = explode('>', $key);
    $result = array_merge_recursive($result, $treeBuilder($hierarchy));
}
var_dump($result);

谢谢您尝试这个。生成的数组结构看起来非常完美,除了所有返回的数组中存在一个键为0,值为null的问题。它似乎是来自代码 return array($numArray[0] => null) - Dave O'Dwyer
是的,你说得对,我认为这是由于没有分隔符的“集合”条目引起的。 - NiMeDia

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