[PHP] 随机生成 6 位字符串问题

2015-03-26 17:45:47 +08:00
 50480350
function createStr($num = 700, $len = 6){
    $numbers = range(0, 9);
    $letters = range('a', 'z');
    $uppers = range('A', 'Z');

    $elements = array_merge($numbers, $letters, $uppers);

    $n = 0;
    $strings = [];

    for($i = 0;$i < $num;$i++){
        $str = '';
        $keys = array_rand($elements, $len);
        foreach($keys as $key){
            $str .= $elements[$key];
        }

        if(in_array($str, $strings)){
            $i--;
            unset($str);
        }else{
            $strings[] = $str;
            unset($str);
//            echo $i. '->' .$str. "\r\n";
        }

        $n++;
    }

    print_r($strings);exit;
//    echo "\r\n\r\n".$n;
}

问题:
当使用 $strings 数组保存时,在 $num = 630 以上时会造成无响应(命令行也是不出结果,一直跑),而630以下,则正常。

P.S. 目前只测了 $len = 6 的情况。
P.S.2 当使用正常的 echo 时,程序可以跑通。

3165 次点击
所在节点    问与答
16 条回复
coosir
2015-03-26 17:59:43 +08:00
我跑没问题呀,试过其他机器上跑么?PHP啥版本?
owei
2015-03-26 18:04:09 +08:00
为什么不用uniqid这个函数来计算
50480350
2015-03-26 18:11:15 +08:00
@coosir 你把 num 调大一下,跑一跑试试。。
50480350
2015-03-26 18:15:09 +08:00
@owei 这个是同事测试发现的,他之前用 do...while 只能跑到 522 个,我改写了下能坚持到630,但还是不能支持更多的。。。 - -#
shiny
2015-03-26 18:22:27 +08:00
kn007
2015-03-26 18:24:45 +08:00
测试没问题,啥版本php,乃们不要黑php好伐,php是世界上最好的语言
kn007
2015-03-26 18:25:32 +08:00
@shiny 这是虾米软件
shiny
2015-03-26 18:32:43 +08:00
@kn007 CodeRunner2
kn007
2015-03-26 18:33:36 +08:00
@shiny 谢谢
kn007
2015-03-26 18:34:06 +08:00
@shiny 没有mac,不能用,不开心
raincious
2015-03-26 18:35:22 +08:00
@owei +1

这个问题在于array_rand给出的并不完全是随机数,所以你需要调用srand来来确保它的随机化。

我用简化过的代码进行了测试(并不保证更快)
https://gist.github.com/raincious/f30728065b77293f1d3e

如果你去掉了代码里的srand,那么循环会在某处卡住,因为array_rand总是在给出之前的序列。加了srand就好多了。

http://php.net/manual/zh/function.srand.php

对于这个问题的解决方案是:
1、加上srand;
2、或者用shuffle来随机化那些数组的key,效率应该不会慢很多(如果你不是一次性批量产生巨多的话)。
50480350
2015-03-26 18:42:30 +08:00
@shiny 经你提醒后,我在linux下测试也是正常了。

@raincious 感谢解惑,就是这个问题,没接触过 srand(),一会去好好看看。

谢谢 LS 各位。
shiny
2015-03-26 19:50:16 +08:00
每次都用 in_array search 一次 value 会导致性能下降。建议在生成完毕后再去重,或者生成的随机字符串作为 key 来保证唯一性。在 $num = 50000 的时候效果比较明显,下面是一个例子:

https://gist.github.com/3f1afdbfcc465db1dd5f.git
shiny
2015-03-26 19:50:52 +08:00
magicianzrh
2015-03-27 00:23:09 +08:00
如果你只要小写么 直接random+md5方便点
比如
<?php
$total = 300000;
$num=0;
$tmp = "";
$len = 6;
mt_srand(time());
$arr = array();
while($num<$total){
if(strlen($tmp) < $len) {
$tmp .=md5(mt_rand(0,mt_getrandmax()));
}
$str = substr($tmp,0,$len);
$tmp = substr($tmp,$len);
array_push($arr,$str);
$num++;
}
echo count(array_unique($arr));
?>
50480350
2015-03-27 08:58:55 +08:00
@magicianzrh @shiny 谢谢二位,正在尝试 :)

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/179545

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX