php - 如何计算一系列字符的笛卡尔幂?

标签 php string range cartesian-product

我想制作一个能够使用 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;
        }
    }
}

See it in action

关于php - 如何计算一系列字符的笛卡尔幂?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17040134/

相关文章:

php - 什么是自动加载;如何使用 spl_autoload、__autoload 和 spl_autoload_register?

在C中按字母顺序比较字符串

python - 过滤字典 'like' 字符串

python - 从 Python 中的字符串中删除表情符号

php - 将 dateTime 插入 mysql 不起作用

php - 使用 ENGINE 子句在迁移中创建表失败

php - “walk”使用多线程(异步)和hack(HHVM)的PHP数组

php - 在 mysql、php 中搜索年龄范围

ios - 从 unicode 字符符号获取范围。 swift

java - 快速查找某个范围包含数字的方法