伪随机字符串

3
我需要从这些字母中生成代码。
$a = array(
    'B','C','D','F','G','H','J','K','L','M','N','O',
    'P','Q','R','S','T','V','W','X','Y','Z','1','2',
    '3','4','5','6','7','8','9','0'
);

但是有两个条件:每个代码必须是唯一的且包含10个字母。我不想使用随机方式,因为效率低下。相反,我想要按照每个字母进行生成,例如:

  1. BBBBBBBBBB
  2. BBBBBBBBBC
  3. BBBBBBBBBD

等等... 有什么好的想法吗?


为什么不直接使用类似于 uniqid 的东西呢?我可以保证这比自己构建字符串要高效得多。 - lonesomeday
我需要生成1.6百万个代码并将它们保存到数据库中。如何使用uniqid? - ariel
4个回答

4

我认为您实际想要的是一个顺序数字列表(因此根本不是随机的),其具有相当不寻常的基数系统。 因此,BBBBBBBBB0,而BBBBBBBC1。 这并不难做,但显然您必须自己编写代码。 可以尝试以下内容:

function generate($num) {
    $num = base_convert($num, 10, 32); // convert the number to base 32
    $num = str_pad($num, 10, "0", STR_PAD_LEFT); // pad it with zeros to the left
    $num = str_replace(array(
        '0','1','2','3','4','5','6','7','8','9','a','b',
        'c','d','e','f','g','h','i','j','k','l','m','n',
        'o','p','q','r','s','t','u','v'
    ), array(
        'B','C','D','F','G','H','J','K','L','M','N','O',
        'P','Q','R','S','T','V','W','X','Y','Z','1','2',
        '3','4','5','6','7','8','9','0'
    ), $num); // replace the normal characters with your custom array

    echo $num, "\n";
}

for ($i = 0; $i < 10; $i++) generate($i);

显然,你可以在 for 语句中更改 10 为任何你想要的数字,并将其插入到数据库中而不是使用 echo。显然,生成1.6百万条记录需要一些时间。
上述代码会产生以下输出:
BBBBBBBBBB
BBBBBBBBBC
BBBBBBBBBD
BBBBBBBBBF
BBBBBBBBBG
BBBBBBBBBH
BBBBBBBBBJ
BBBBBBBBBK
BBBBBBBBBL
BBBBBBBBBM

聪明的解决方案,但速度相当慢。 - Peter
@PeterSzymkowski 嗯,没错。但是让我们面对现实吧:如果速度是目标,解决方案就是使用普通的数字。 - lonesomeday
+1,这绝对是最简单的答案,可以完成工作。需要考虑一件事情(这适用于任何方法),即您需要即时将其存储在数据库中,因为填充生成值的数组将消耗大量内存。 - DaveRandom
惊人的是,在我的开发机上,@PeterSzymkowski的解决方案快了6倍以上。 - DaveRandom

3
<?php

$length = 3;

$letters = str_split("ABC"); // define your dictionary here

$index = array_fill(0, $length, 0);

$key = $length - 1;
while(true) {   
    $code = "";
    for($i=0;$i<$length;$i++) {     
        $code .= $letters[$index[$i]];      
    }
    echo $code ."<br/>"; // output code

    $index[$key]++;

    while(!isset($letters[$index[$key]])) {
        $index[$key] = 0;
        $key--;
        if($key < 0) {
            break 2;
        }       
        $index[$key]++;
    }   
    $key = $length - 1; 
}

Example:


很好的解决方案,但是将 $index = Array(); for($i=0;$i<$length;$i++) { $index[$i] = 0; } 替换为 $index = array_fill(0, $length, 0); - Sergey
就此而言,这里有一个Codepad,其中包含OP所请求的格式和字典。这确实比我的解决方案快得多(5到10倍),因此大力点赞。 - lonesomeday

1
<?php

$a = array(
    'B','C','D','F','G','H','J','K','L','M','N','O',
    'P','Q','R','S','T','V','W','X','Y','Z','1','2',
    '3','4','5','6','7','8','9','0'
);

function key_increment (&$symbols, $position = null) 
{
    global $a;
    if ($position === null) $position = count($symbols) - 1;
    if ($position == -1) return;

    $index = $symbols[$position];
    $index ++;
    if (!isset($a[$index])) {
        $v = 0;
        key_increment ($symbols, $position-1);
    }
    $symbols[$position] = $value;
}

function generate($length, $total) 
{
    global $a;

    $symbols = array_fill(0, $length, 0);


        for ($i = 0; $i < $total; $i ++) {
            $code = '';
        foreach ($symbols as $index) {
            $code .= $a[$index];
        }
        echo $code;
        echo '<br />';

        key_increment($symbols);
    }
}

generate(3, 100);

@PeterSzymkowski,是的,但它清楚地展示了它必须如何工作。lonesomeday的问题更好。 - Sergey
这段代码显然可以工作,但是它很难理解。你能否使用描述性的变量名,而不是 $s$v 等等? - lonesomeday

0
最好使用uniqid,特别是因为您将生成160万个代码。如果您担心大小写问题,只需使用strtoupper()即可。
echo strtoupper(uniqid());

生成所有这些并将它们插入需要相当长的时间。

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