创建父母和孩子的阵列

时间:2017-08-15 16:35:38

标签: php arrays

我有一个数组,我知道所需的输出,但我无法理解如何实现它

初始索引是"父母" id' s,其中包含的数组是孩子,但有些孩子也是父母

我的阵列: ```

array:10 [▼
  0 => array:2 [▼
    0 => 1
    1 => 5
  ]
  1 => array:1 [▼
    0 => 2
  ]
  2 => array:2 [▼
    0 => 3
    1 => 4
  ]
  5 => array:1 [▼
    0 => 6
  ]
  6 => array:2 [▼
    0 => 7
    1 => 8
  ]
  9 => array:2 [▼
    0 => 10
    1 => 22
  ]
  10 => array:1 [▼
    0 => 11
  ]
  11 => array:10 [▼
    0 => 12
    1 => 13
    2 => 14
    3 => 15
    4 => 16
    5 => 17
    6 => 18
    7 => 19
    8 => 20
    9 => 21
  ]
  22 => array:1 [▼
    0 => 23
  ]
  23 => array:2 [▼
    0 => 24
    1 => 25
  ]
]

```

结果数组: ```

0
9
0,1
0,5
0,1,2
0,1,2,3
0,1,2,4
0,5,6
0,5,6,7
0,5,6,8
9,10
9,22
9,10,11
9,10,11,12
9,10,11,13
9,10,11,14
9,10,11,15
9,10,11,16
9,10,11,17
9,10,11,18
9,10,11,19
9,10,11,20
9,10,11,21
9,22,23
9,22,23,24
9,22,23,25

```

我正在考虑使用递归,但我不能为我的生活找出如何获得结果

编辑:更多信息:

如果我采取:

  22 => array:1 [▼
    0 => 23
  ]
  23 => array:2 [▼
    0 => 24
    1 => 25
  ]

23是24和25的父母,22是23的父母,因此22是24和25的祖父母:

9,22,23,24
9,22,23,25

你是如何得到这个清单的(9显然是22的父母,因此是23岁的祖父母和24岁和25岁的祖父母)

1 个答案:

答案 0 :(得分:1)

这有点高级,但您可以使用Iterators来实现这一目标。

首先,我们必须延长RecursiveIteratorIterator以满足我们的需求:

class FlatRecursiveIteratorIterator extends RecursiveIteratorIterator
{
    private $directory;

    public function __construct(
        Traversable $iterator,
        $mode = RecursiveIteratorIterator::LEAVES_ONLY,
        $flags = 0,
        array $directory
    ) {
        // Set array for children lookup.
        $this->directory = $directory;
        parent::__construct($iterator, $mode, $flags);
    }

    public function callHasChildren()
    {
        if ($this->getDepth() === 0 && is_array($this->current())) {
            return true;
        }

        // See if children array availale in the top most array
        // (lookup by id).
        return !empty($this->directory[$this->current()]) &&
            is_array($this->directory[$this->current()]);
    }

    public function callGetChildren()
    {
        return new RecursiveArrayIterator(
            $this->getDepth() === 0 
                ? $this->current()
                : $this->directory[$this->current()]
        );
    }
}

有了这个课程,我们会将其与RecursiveArrayIteratorRecursiveCallbackFilterIterator结合使用,以创建所需的$iterator

$skip = [];
$iterator = new FlatRecursiveIteratorIterator(
    // This filter helps up skip top level array elements
    // if they have ancestors. Pay attencion that $skip passed by reference.
    new RecursiveCallbackFilterIterator(
        new RecursiveArrayIterator($array),
        function ($current, $key, $_) use (&$skip) {
            return !(is_array($current) && isset($skip[$key]));
        }
    ),
    RecursiveIteratorIterator::SELF_FIRST,
    0,
    $array
);

然后我们可以使用一个非常简单的非嵌套循环来遍历这个$iterator

$stack = [];
foreach ($iterator as $node) {
    $depth = $iterator->getDepth();    
    if ($depth > 0) {
        $skip[$node] = true;
    }

    // Use ternary operator as top most array has ids as keys,
    // but inner arrays have ids as values.
    $stack[$depth] = $depth === 0
        ? $iterator->key()
        : $node;

    // We have to slice out stack, as it may contain elements
    // from previous iterations.
    echo implode(',', array_slice($stack, 0, $depth + 1)), PHP_EOL;
}

这是working demo

这可能看起来像很多代码,但实际上并非如此。我们需要考虑到大部分工作都是由Standard PHP Library完成的。我们只编写了大多数案例特定的代码。