【问题标题】:How can I build an associative array recursively using keys from another array?如何使用来自另一个数组的键递归地构建关联数组?
【发布时间】:2015-04-01 03:33:21
【问题描述】:

好的,所以这有点棘手,我碰壁了。

我拥有的是一组分组选项:

Array
(
    [0] => Array
        (
            [9] => sum
            [10] => sum
            [11] => avg
        )

    [4] => Array
        (
            [9] => sum
            [10] => sum
            [11] => avg
        )

    [9] => Array
        (
            [9] => sum
            [10] => sum
            [11] => avg
        )

)

我想要得到的是一个如下所示的数组:

Array
(
    [0] => Array
        (
            [4] => Array
                (
                    [9] => Array
                        (
                            [9] => sum
                            [10] => sum
                            [11] => avg
                        )
                )
        )
)

我这个例子只显示了 3 个层次,但我需要它是动态的,因为会有不同的分组选项可用。有些只有 1 个级别,这很容易,但也会有 2 个或更多。嵌套级别应始终具有与父级别相同的键。

我正在做的是使用它来迭代数据。键是我正在分组的数据数组中的索引。问题是,我需要较低级别的分组来了解其他索引,因为这是对多个数据集进行正确分组所必需的。这是为了尝试简化处理大型数据集。我只需要计算最低级别(在此示例中为 9),因此我可以遍历最终数组来计算每个父分组的分组数据。我将使用关键 9 数据来构建关键 4 数据和关键 4 数据来构建关键 0 数据。键需要了解父组的原因是数据对于父组是唯一的。 $a[0][4][9] 与 $a[0]、$a[4]、$a[9] 不同。我需要 9 才能知道它依赖于 4 而 4 依赖于 0。

我不确定 PHP 是否可以做到这一点,或者这是否有意义。你能像这样动态构建一个数组吗?

【问题讨论】:

  • 为什么会得到上面的数组,为什么要换成下一个数组?键会改变其他值吗?
  • 我们是否需要检查子数组是否相同?这些树会比你展示的更复杂吗?
  • @RyanVincent 如果它们不相同,您将无法获得 OP 想要的输出
  • 它们应该是相同的,基本上,父组将对每个子组的数据进行求和或平均。而最低的孩子是唯一处理所有数据的孩子。原始数组是用户选择的分组选项传递的参数。我需要获取该数组并在上面构建所需的数组。

标签: php arrays algorithm multidimensional-array


【解决方案1】:

这是另一个递归“树”,除了它是“单向”而不是“多向”。即它是一个“链表”。 “节点数据”仅存储在最终节点中,因为它在每个节点中都是相同的。

像往常一样:Working code at Codepad.org

我发现弄清楚我应该用什么“初始化”输出以及用什么“递归”非常“有趣”。反正这里是代码...

我决定在一开始就明确处理一些“特殊情况”来简化代码...

if (count($source) <= 0) {
    return array();
}
elseif (count($source) == 1) {
    return array(key($source) => current($source));
}

接下来,完成这项工作的函数......

/**
 * Add all nodes to the 'tree'
 *
 * @param type $outNode -- a 'reference' to the current node to be added to
 * @param type $curKey  -- the index of the current node -- need this when overwriting the 'null' value later.
 * @param type $source  -- a reference to the source array as i do not want a copies to be made
 *
 * @return array -- current node
 */
function addNode(&$outNode, $curKey, &$source)
{
    // get the current node details...
    $curKey = key($source);
    $curItems = current($source);

    // advance to the next source node...
    next($source);

    // Is this the final node in the list?
    if (current($source) !== false) { // more nodes to add. We need to recurse...
        $nextKey = key($source);

        $outNode[$curKey] = array($nextKey => null);
        return addNode($outNode[$curKey], $nextKey, $source); // recurse
    }

    // add the items to the last node
    $outNode[$curKey] = $curItems;

    return $outNode;
}

起始条件和构建输出...

// generated tree in here
$outTree = array();

// I use the key(), current() and next() functions as I use the 'internal' array iterator.
$curKey = key($source);
$curItems = current($source);

$outTree[$curKey]  = null; // the 'null' always gets overwritten later.

// build the tree...
$lastNode = addNode($outTree, $curKey,  $source);

// show the output...
echo '<pre>';
print_r($outTree);
echo '</pre>';
exit;

使用提供的数据输出:

Array
(
    [0] => Array
        (
            [4] => Array
                (
                    [9] => Array
                        (
                            [9] => sum
                            [10] => sum
                            [11] => avg
                        )
                )
        )
)

【讨论】:

  • 这很完美!谢谢你的帮助。我从未见过这个,所以我正在玩它以更好地理解它。非常好!
【解决方案2】:

正如你所说,这将是动态的,首先你需要知道你的数组的第一个索引,我称之为$last,因为在循环中是最后使用的索引:

$last = array_search(array_slice($array, 0, 1), $array);

然后在$temp 中,在循环之前和循环中保存数组定义。

在循环之后,您需要添加深层数组的值(在本例中为 var_export),并且您需要添加所有决赛 )(在本例中为 str_repeat

$temp .= var_export($array[$last], true) . str_repeat(')', $i);

当你有最终的字符串(数组定义)时,只需调用eval

eval($temp . ';');

查看代码:

<?php

$array = Array
(
    0 => Array
        (
            9 => 'sum',
            10 => 'sum',
            11 => 'avg'
        ),

    4 => Array
        (
            9 => 'sum',
            10 => 'sum',
            11 => 'avg'
        ),

    9 => Array
        (
            9 => 'sum',
            10 => 'sum',
            11 => 'avg'
        )
);

$last = array_search(array_slice($array, 0, 1), $array);
$temp = "\$newArray = ";
$i = 0;

foreach($array as $key => $value) {
  $temp .= "array({$key} => ";
  $last = $key;
  $i++;
}

$temp .= var_export($array[$last], true) . str_repeat(')', $i);

eval($temp . ';');

echo '<pre>';
print_r($newArray);
echo '</pre>';

输出:

Array
(
    [0] => Array
        (
            [4] => Array
                (
                    [9] => Array
                        (
                            [9] => sum
                            [10] => sum
                            [11] => avg
                        )

                )

        )

)

【讨论】:

  • @Jeremy 你有预付款吗?
  • 今晚我将对此进行测试。感谢您的反馈意见。我不确定是否要使用 eval 但如果这是我唯一的选择,那就这样吧。
猜你喜欢
  • 2014-10-24
  • 2011-02-10
  • 2019-07-20
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-01-28
相关资源
最近更新 更多