V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
V2EX 提问指南
50480350
V2EX  ›  问与答

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

  •  
  •   50480350 · 2015-03-26 17:45:47 +08:00 · 3280 次点击
    这是一个创建于 3531 天前的主题,其中的信息可能已经有所发展或是发生改变。
    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 时,程序可以跑通。

    16 条回复    2015-03-27 08:58:55 +08:00
    coosir
        1
    coosir  
       2015-03-26 17:59:43 +08:00
    我跑没问题呀,试过其他机器上跑么?PHP啥版本?
    owei
        2
    owei  
       2015-03-26 18:04:09 +08:00   ❤️ 1
    为什么不用uniqid这个函数来计算
    50480350
        3
    50480350  
    OP
       2015-03-26 18:11:15 +08:00
    @coosir 你把 num 调大一下,跑一跑试试。。
    50480350
        4
    50480350  
    OP
       2015-03-26 18:15:09 +08:00
    @owei 这个是同事测试发现的,他之前用 do...while 只能跑到 522 个,我改写了下能坚持到630,但还是不能支持更多的。。。 - -#
    shiny
        5
    shiny  
       2015-03-26 18:22:27 +08:00
    kn007
        6
    kn007  
       2015-03-26 18:24:45 +08:00
    测试没问题,啥版本php,乃们不要黑php好伐,php是世界上最好的语言
    kn007
        7
    kn007  
       2015-03-26 18:25:32 +08:00
    @shiny 这是虾米软件
    shiny
        8
    shiny  
       2015-03-26 18:32:43 +08:00
    @kn007 CodeRunner2
    kn007
        9
    kn007  
       2015-03-26 18:33:36 +08:00
    @shiny 谢谢
    kn007
        10
    kn007  
       2015-03-26 18:34:06 +08:00
    @shiny 没有mac,不能用,不开心
    raincious
        11
    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
        12
    50480350  
    OP
       2015-03-26 18:42:30 +08:00
    @shiny 经你提醒后,我在linux下测试也是正常了。

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

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

    https://gist.github.com/3f1afdbfcc465db1dd5f.git
    shiny
        14
    shiny  
       2015-03-26 19:50:52 +08:00
    magicianzrh
        15
    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
        16
    50480350  
    OP
       2015-03-27 08:58:55 +08:00
    @magicianzrh @shiny 谢谢二位,正在尝试 :)
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   2745 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 24ms · UTC 00:18 · PVG 08:18 · LAX 16:18 · JFK 19:18
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.