如何在数组中生成不存在的标识符?

时间:2018-06-27 12:55:53

标签: php performance unique uuid combinatorics

我想生成一个长度为12个字符的唯一值。要生成唯一值,请使用以下方法:

function generate_unique_id()
{
    $time = substr(time(), -7);
    $month = mb_strtolower(date("M"));
    $symbol = "OM";
    $string = $month."".$time."".$symbol;
    $result = str_shuffle($string);
    return $result;
}

我测试了此代码以生成30,000个唯一值,但是每次退出循环时都不会生成所需的唯一标识符。

$array = [];

for($i=0; $i<=3; $i++)
{
    $unique_id = generate_unique_id();
    if(in_array($unique_id, $array)){
        echo $i;
        break;
    }
    $array[] = $unique_id;
}

如何知道生成的长度为12个字符串的唯一值的数量,如果生成能力未达到最大数量限制,如何快速生成一个唯一值。

2 个答案:

答案 0 :(得分:1)

未经测试,应该可以运行(随机前缀+十六进制计数器后缀):

<?php

function unique_id($length = 12)
{
    static $counter = 0;
    $suffix = dechex($counter);
    $prefixLen = $length - strlen($suffix);
    $prefix = substr(uniqid(), -$prefixLen);
    $counter++;
    return $prefix.$suffix;
}

$arr = array();
for ($i = 0; $i < 30000; $i++)
{
    $id = unique_id();
    if (in_array($id, $arr))
    {
        echo $id."\n";
        break;
    }
    $arr[]= $id;
}

echo "Generated ".count($arr)." unique IDs.\n";

请注意,这仅在您需要一个请求/脚本执行中的所有ID时才有效。新的请求将导致静态$counter变量重新开始,从而不再保证唯一的ID。

答案 1 :(得分:1)

下面的代码在 21.378324985504 1 秒内生成了 30,000 个唯一ID。

$ids = [];

while (count($ids) < 30000) {
  $id = bin2hex(random_bytes(6));

  if (!in_array($id, $ids)) array_push($ids, $id);
}

var_dump(count($ids));
var_dump($ids);

上面的代码将继续生成ID,直到获得30,000个唯一ID为止,没有理由break

1 生成时间可能会有所不同。

实时示例

Repl

更新#1

对于那些没有PHP 7的用户,可以使用this函数。

更新#2

根据@cckep评论,此代码段的效率大大提高:

$time_start = microtime(true); 
$ids = [];

while (count($ids) < 30000) {
  $id = bin2hex(random_bytes(6));

  if (!isset($ids[$id])) $ids[$id] = true;
}

$ids = array_keys($ids);

$time_end = microtime(true);
$execution_time = ($time_end - $time_start);

var_dump(count($ids));
var_dump($ids);

echo $execution_time;