我想制作一个能够使用 a-z,0-9 生成字母和可选数字列表的函数。
$output = array();
foreach(range('a','z') as $i) {
foreach(range('a','z') as $j) {
foreach(range('a','z') as $k) {
$output[] =$i.$j.$k;
}
}
}
谢谢
例子:
myfunction($include, $length)
用法是这样的:
myfunction('a..z,0..9', 3);
输出:
000
001
...
aaa
aab
...
zzz
输出将包含字母和数字的所有可能组合。
最佳答案
搭建舞台
首先,使用 range
将 "0..9"
等字符串扩展为 "0123456789"
的函数:
function expand_pattern($pattern) {
$bias = 0;
$flags = PREG_SET_ORDER | PREG_OFFSET_CAPTURE;
preg_match_all('/(.)\.\.(.)/', $pattern, $matches, $flags);
foreach ($matches as $match) {
$range = implode('', range($match[1][0], $match[2][0]));
$pattern = substr_replace(
$pattern,
$range,
$bias + $match[1][1],
$match[2][1] - $match[1][1] + 1);
$bias += strlen($range) - 4; // 4 == length of "X..Y"
}
return $pattern;
}
它处理任意数量的可扩展模式并注意保留它们在源字符串中的位置,例如
expand_pattern('abc0..4def5..9')
将返回 "abc01234def56789"
。
一次计算结果
现在我们可以很容易地进行这种扩展,下面是一个函数,它在给定一串允许的字符和一个长度的情况下计算笛卡尔积:
function cartesian($pattern, $length) {
$choices = strlen($pattern);
$indexes = array_fill(0, $length, 0);
$results = array();
$resets = 0;
while ($resets != $length) {
$result = '';
for ($i = 0; $i < $length; ++$i) {
$result .= $pattern[$indexes[$i]];
}
$results[] = $result;
$resets = 0;
for ($i = $length - 1; $i >= 0 && ++$indexes[$i] == $choices; --$i) {
$indexes[$i] = 0;
++$resets;
}
}
return $results;
}
例如,要获得问题中描述的输出
$options = cartesian(expand_pattern('a..z0..9'), 3);
See it in action (我将扩展长度限制为2,这样输出就不会爆炸)。
动态生成结果
由于结果集可能非常大(它随 $length
呈指数增长),一次生成所有结果可能会让人望而却步。在那种情况下,可以重写代码,使其依次返回每个值(迭代器样式),由于 generators,这在 PHP 5.5 中变得非常容易:
function cartesian($pattern, $length) {
$choices = strlen($pattern);
$indexes = array_fill(0, $length, 0);
$resets = 0;
while ($resets != $length) {
$result = '';
for ($i = 0; $i < $length; ++$i) {
$result .= $pattern[$indexes[$i]];
}
yield $result;
$resets = 0;
for ($i = $length - 1; $i >= 0 && ++$indexes[$i] == $choices; --$i) {
$indexes[$i] = 0;
++$resets;
}
}
}
关于php - 如何计算一系列字符的笛卡尔幂?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17040134/