生成并保存数百万个唯一身份代码

时间:2015-12-09 13:40:38

标签: mysql laravel

我正在使用Laravel 5.1框架。

我需要从字符'BCDFGHIJKLMNPQRSTVWXYZ'取5来创建一组唯一代码,例如DFGHJ。

所以,我的代码是这样的:

$maxCodes = 1200000;
$codeSize = 5;
$characters = 'BCDFGHJKLMNPQRSTVWXY';
$cLenght = strlen($characters);
$sizeBlock = $maxCodes/($cLenght*4); // For not overflow memory when put the codes in array

for ($i=0; $i < $cLenght; $i++) {
    $subCharacters = str_replace($characters[$i], '', $characters);
    $existCodes = [];
    for ($k = 0; $k < 4; $k++) {
        $codesToInsert = [];
        for ($j = 0; $j < $sizeBlock;) {
            $code = $characters[$i] . substr(str_shuffle($characters), 0, $codeSize-1); 

            if (!isset($existCodes[$code])) {
                $existCodes[$code] = '';
                array_push($codesToInsert, ['code' => $code, 'used' => 0, 'rand' => rand(0,10)]);
                $j++;
            }
        }

        \App\Code::insert($codesToInsert);
    }
}

我会解释一下我的代码。因为我的代码是按字母顺序排列的,所以我用一个随机数放置了一个字段rand(我为下一个创建了这个字段,像Code :: where('used',0) - &gt; where('rand',rand( 0,9)),通过这种方式我检索一个随机代码,而不是按字母顺序)

问题是当我运行函数生成代码时,它只创建135000而不是$ maxCodes,但我不知道为什么?..

有人可以帮助我吗?

谢谢!

PS.-对不起我的英文..

1 个答案:

答案 0 :(得分:0)

代码被评论。

限制:越接近组合的限制,那么'重复生成的计数'将变得愚蠢。我希望在我的电脑上生成所有120万个代码需要大约30分钟。我希望它可以长达150万。很有意思。

字母'B'的详细信息,包含重复计数的样本

$tryCount integer89166
$existCount integer68422

Timings:

Script start date and time : 2015-12-09 15:45:47.172
Script stop end date and time: 2015-12-09 15:46:40.109
Total execution time : 52.938000000000002

示例:

'BXCLF' => integer 6
'BYRXS' => integer 6
'BPGGG' => integer 6
'BRQJJ' => integer 6
'BKJKQ' => integer 6
'BNQVG' => integer 6
'BLQSX' => integer 6
'BCGDH' => integer 5
'BBLFG' => integer 5
'BFBJQ' => integer 5 
'BRVRJ' => integer 5
'BJXTX' => integer 5

硬件:PC - 双仓鼠供电。

RandomData类的代码:Random data for use in PHP

代码:

<?php

include __DIR__ . '/__bootstrap__.php';

use app\system\encryption\RandomData;
use app\system\ElapsedTiming;

$maxCodes =  50000;
$codeSize = 5;
$characters = 'BCDFGHJKLMNPQRSTVWXY';
$cLength = strlen($characters) - 1;

$codesPerLetter = (int) $maxCodes / $cLength; // how many to generate for this initial letter

$timer = new ElapsedTiming();
$timer->start();

/**
 * @var RandomData
 */
$randSrc = RandomData::instance(); // source of random numbers

for ($i=0; $i < $cLength; $i++) { // use each char as an initial character

    $existCodes = array(); // current batch of codes in here
    $existCount = 0;

    $newCode = $characters[$i] . '0000'; // each `batch` starts with a different letter
                                         // then four random letters from the string...

    $tryCount = 0; // count the number of attemps to generate the required count
    while ($existCount < $codesPerLetter) {

        // generate a random 4 character string using all the characters
        for ($k = 1; $k < 5 ; $k++) { // first lether is fixed then fill in the rest
            // generate code...
            $char = $characters[$randSrc->int32(0, $cLength)];
            $newCode[$k] = $char;
        }

        $tryCount++;

        // test if exists
        if (isset($existCodes[$newCode])) { // store as keys not values
            $existCodes[$newCode]++;         // count duplicate generation
        }
        else {
            $existCodes[$newCode] = 1;       // a new one
            $existCount++;                   // closer to the target
        }
    }

    /**
     * Write this batch of codes to the array to the database...
     */
}

/* debug information */
$timer->stop();
arsort($existCodes);

$timer->printFullStats();

\Kint::dump($tryCount, $existCount, array_slice($existCodes, 0, 100));