如何使用不确定数量的子数组循环遍历数组

时间:2015-06-18 11:14:56

标签: php arrays

我试图在我的应用中列出具有子类别的类别 - 我可以使用PHP或Javascript / Jquery进行以下操作:

我有一个类别数组,附加了子类别作为附加数组

诀窍在于它可以像子类别那样深入。 和子类别也可以有子类别。

因此,对于每个类别,它可以拥有尽可能多的孩子,每个孩子可以拥有许多子阵列。

循环创建下拉列表的最佳方法是什么?

这是转储主数组时的结构:

array (size=2)
  0 => 
    array (size=4)
      'id' => int 1
      'name' => string 'Stationery' (length=10)
      'parent_id' => int 0
      'childs' => 
        array (size=1)
          0 => 
            array (size=4)
              ...
  1 => 
    array (size=3)
      'id' => int 4
      'name' => string 'boots' (length=5)
      'parent_id' => int 0

通知子零有一个"孩子"排列 当转储这个数组时,我得到:

array (size=1)
  0 => 
    array (size=4)
      'id' => int 2
      'name' => string 'pens' (length=4)
      'parent_id' => int 1
      'childs' => 
        array (size=1)
          0 => 
            array (size=4)
              ...

请注意,这也有附加的子项,在转储时看起来像:

array (size=1)
  0 => 
    array (size=4)
      'id' => int 3
      'name' => string 'penfillers' (length=10)
      'parent_id' => int 2
      'childs' => 
        array (size=1)
          0 => 
            array (size=3)
              ...

偷偷摸摸 - 这个还有另一个孩子!

这可以像子类别一样深入

我如何循环浏览它们并将输出放在下拉列表中? 我很难过如何无限循环直到链条结束。

由于 杰森

3 个答案:

答案 0 :(得分:1)

您应该递归地生成数组中的所有选项。有两种方法可以实现它。取决于您的PHP版本。

为了使核心逻辑更清晰,假设我们使用这些实用程序渲染输出:

//
// some function to tidy up outputs
//

// simply make the recursive level visible
function pad_level($string, $level) {
    // no pad for 0 level
    if ($level == 0) return $string;

    // pad some '-' to show levels
    $pad = str_repeat('-', $level);
    return $pad . ' ' . $string;
}

// render a leaf into standardized info array for an option
function option_from($item, $level) {
    return array(
        'value' => $item['id'],
        'display_value' => pad_level($item['name'], $level),
    );
}

// render options into HTML select
function render_select($name, $options) {
    $output = '';
    foreach ($options as $option) {
        $output .= '  '.
            '<option value="'.htmlspecialchars($option["value"]).'">'.
            htmlspecialchars($option["display_value"]).
            '</option>'."\n";
    }
    return '<select name="'.htmlspecialchars($name).'">'."\n".
        $output."</select>\n";
}

// render options into plain text display
function render_plain_text($name, $options) {
    $output = '';
    foreach ($options as $option) {
        $output .= $option["value"].' => '.$option["display_value"]."\n";
    }
    return $output;
}

这是两种方法:

//
// core logic
//

// Method 1: Generator. Available with PHP 5 >= 5.5.0
function options_in($array, $level=0) {
    foreach ($array as $leaf) {
        yield option_from($leaf, $level);

        // yield the children options, if any
        if (isset($leaf['childs']) && is_array($leaf['childs'])) {
            foreach (options_in($leaf['childs'], $level+1) as $option) {
                yield $option;
            }
        }
    }
}

// Method 2: Normal recursion then merge arrays. For PHP 4 or after
function get_options($array, $level=0) {
    $output = array();

    // yield for the option array
    foreach ($array as $leaf) {
        $output[] = option_from($leaf, $level);
        // yield the children
        if (isset($leaf['childs']) && is_array($leaf['childs'])) {
            $childs = get_options($leaf['childs'], $level+1);
            $output = array_merge($output, $childs); // this could be slow
        }
    }

    return $output;
}

这就是你实际渲染HTML的方法:

// dummy input
$input = array(
    array(
        'id' => 1,
        'name' => 'Stationery',
        'parent_id' => 0,
        'childs' => array(
            array(
                'id' => 2,
                'name' => 'Pencil',
                'parent_id' => 1,
            ),
            array(
                'id' => 3,
                'name' => 'Pen',
                'parent_id' => 1,
            ),
            array(
                'id' => 5,
                'name' => 'Notepad',
                'parent_id' => 1,
                'childs' => array(
                    array(
                        'id' => 8,
                        'name' => 'Blue Pad',
                        'parent_id' => 3,
                    ),
                    array(
                        'id' => 9,
                        'name' => 'Red Pad',
                        'parent_id' => 3,
                    ),
                    array(
                        'id' => 10,
                        'name' => 'iPad',
                        'parent_id' => 3,
                    ),
                ),
            ),
        ),
    ),
    array(
        'id' => 4,
        'name' => 'boots',
        'parent_id' => 0,
    ),
);

// method 1, preferred
echo "\nMethod 1\n";
echo render_select('mySelect', options_in($input));
echo render_plain_text('mySelect', options_in($input));

// method 2
echo "\nMethod 2\n";
echo render_select('mySelect', get_options($input));
echo render_plain_text('mySelect', get_options($input));

答案 1 :(得分:1)

这是一个非常简单的示例,说明如何使用递归来完成它。我确信有更好的方法,但这是一个非常简单的功能,所以你可以看到这个概念。该函数调用自己直到作业完成(我在这里使用方括号数组表示法,所以请确保您的PHP版本支持它)

<?php

    function getItems(array $items)
    {
            $return = [];

            foreach ($items as $item) {
                    $return[] = $item;

                    if (isset($item['childs']) && count($item['childs']) > 0) {
                            $return = array_merge(
                                    $return,
                                    getItems($item['childs'])
                            );
                    }

            }

            return $return;
    }

    $array = [
            0 => [
                    'id' => 1,
                    'childs' => []
            ],
            1 => [
                    'id' => 2,
                    'childs' => [
                            0 => [
                                    'id' => 3,
                                    'childs' => []
                            ]
                    ]
            ]
    ];

    print_r(getItems($array));

然后循环结果以创建您的选择选项。希望这有帮助

答案 2 :(得分:0)

创建一个子函数,子函数的输入将是对象,此函数将检查它是一个数组还是一个简单元素,如果它是一个数组,那么它将在该元素上再次调用该函数,否则返回该元素。 只是精心制作&#34; Gerald Schneider的回答。