生成路径的逻辑算法

4

我希望开发一个算法来创建 Symfony 模板服务。 我想检查模板是否存在于子集路径中,并按顺序排列。

给定参数数组如下(已按我所需的顺序排序):

$params = ['O', 'U', 'W', 'P']

我该如何输出这个数组?
$urls = [
    'O/U/W/P/template',
    'O/U/W/template',
    'O/U/P/template',
    'O/U/template',
    'O/W/P/template',
    'O/W/template',
    'O/P/template',
    'O/template',
    'U/W/P/template',
    'U/W/template',
    'U/P/template',
    'U/template',
    'W/P/template',
    'W/template',
    'P/template',
    'template'
];

我可以用这样的代码对少量参数进行操作(我想每个人都能做到):

private function getPaths($template, $params)
{
    $urls           = [];
    $alreadyPerform = [];
    $paramsCounter = count($params);

    for ($i = 0; $i < $paramsCounter; $i++) {
        for ($j = 0; $j < $paramsCounter; $j++) {
            if ($i !== $j && !in_array($params[$j], $alreadyPerform, true)) {
                $urls[] = sprintf(
                    '/%s/%s/%s.html.twig', $params[$i], $params[$j], $template
                );
            }
        }
        $alreadyPerform[] = $params[$i];
        $urls[] = sprintf('/%s/%s.html.twig', $params[$i], $template);
    }
    $urls[] = sprintf('%s.html.twig', $template);

    return $urls;
}

这个函数之前一直按照我的要求工作(最多3个参数),但是今天我想要添加一个参数,可能以后还会加更多。

非常感谢您的帮助!

谢谢。


1
感谢 @castis 编辑我的丑陋数组! - EhXod
为什么您批准了我的标题编辑(删除[PHP]并将“algo”更改为“algorithm”),然后又回滚到原始状态呢? - cteski
@cteski 对不起,我沉迷于帖子编辑中了... - EhXod
2个回答

2

使用递归,您可以执行以下操作:

/**
 * @param array $elements
 * @param array $extra
 *
 * @return Generator
 */
function gen(array $elements, array $extra = []): \Generator {

    foreach ($elements as $i => $head) {
        foreach (gen(array_slice($elements, $i + 1), $extra) as $tail) {
            yield array_merge([$head], $tail);
        }
    }

    yield $extra;
}

演示: https://3v4l.org/gJB8q


或者不使用递归:

/**
 * @param array $elements
 *
 * @return Generator
 */
function gen2(array $elements): \Generator {

    for ($num = count($elements), $i = pow(2, $num) - 1; $i >= 1; $i -= 2) {
        $r = [];
        for ($j = 0; $j < $num; $j += 1) {
            if ($i & (1 << ($num - $j - 1))) {
                $r[] = $elements[$j];
            }
        }

        yield $r;
    }
}

demo: https://3v4l.org/grKXo


太聪明了,使用生成器是这种情况下最好的选择,我得到了我想要的。非常感谢!(我没有太多声望可以点赞,真糟糕...) - EhXod

1
请考虑使用以下软件包:

https://github.com/drupol/phpermutations

这只是一个非常基本的例子,它能做什么:

$permutations = new \drupol\phpermutations\Generators\Permutations(['A', 'B', 'C'], 2);
foreach ($permutations->generator() as $permutation) {
    echo implode('/', $permutation);
    echo "\n";
}

A/B
B/A
A/C
C/A
B/C
C/B

感谢@jakub-wrona提供的链接。我认为在我的情况下这不是一个好选择,但我稍后会更具体地了解这个包。 - EhXod

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