我正在尝试使用Erlang生成随机字母数字ID。
我天真地尝试crypto:strong_rand_bytes(Bytes)
生成一个随机二进制文件然后使用那个用<<"my_unique_random_id">>
创建的二进制文件 - 这不起作用,因为随机位不一定是有效的UTF-8字符串,对吧? / p>
好吧,我在erlang文档和其他地方寻找其他选项,但我没有找到任何东西。有人能指出我的解决方案吗?
答案 0 :(得分:13)
这可能取决于您需要的随机性。 Erlang的crypto
模块产生比random
模块更强的随机数据(另请参阅[erlang-questions] Yaws security alert - Yaws 1.93和this question)。如果您想使用strong_rand_bytes
生成ID,可能只需获取它的base64就可以了:
> base64:encode(crypto:strong_rand_bytes(Bytes)).
如果需要,您可以将其转换为列表。
答案 1 :(得分:12)
根据Generating random strings in Erlang,只需要几行Erlang就能从一组特定的字符集中生成一个指定长度的字符串。
get_random_string(Length, AllowedChars) ->
lists:foldl(fun(_, Acc) ->
[lists:nth(random:uniform(length(AllowedChars)),
AllowedChars)]
++ Acc
end, [], lists:seq(1, Length)).
博客文章对代码进行了逐行说明。查看几条优化提示的评论。
答案 2 :(得分:3)
我准备了小模块做到这一点
它还使用crypto:rand_uniform/2
但不是过时的random:uniform
module(cloud_rnd).
-export([rnd_chars/1, rnd_numbers/1, rnd_chars_numbers/1]).
rnd_chars(L) -> get_rnd(L, chars).
rnd_numbers(L) -> get_rnd(L, numbers).
rnd_chars_numbers(L) -> get_rnd(L, chars_numbers).
get_rnd(L, chars) -> gen_rnd(L, "abcdefghijklmnopqrstuvwxyz");
get_rnd(L, numbers) -> gen_rnd(L, "1234567890");
get_rnd(L, chars_numbers) -> gen_rnd(L, "abcdefghijklmnopqrstuvwxyz1234567890").
gen_rnd(Length, AllowedChars) ->
MaxLength = length(AllowedChars),
lists:foldl(
fun(_, Acc) -> [lists:nth(crypto:rand_uniform(1, MaxLength), AllowedChars)] ++ Acc end,
[], lists:seq(1, Length)
).
答案 3 :(得分:2)
对各种反应的问题&#34;我需要随机字符串&#34;问题(用任何语言)几乎每个解决方案都使用有缺陷的规范,即字符串长度。问题本身很少揭示为什么需要随机字符串,但我会大胆地假设它们将被用作需要唯一的标识符。
有两种主要方法可以获得严格的唯一字符串:确定性(非随机)和存储/比较(繁重)。该怎么办?放弃鬼魂。改为使用概率唯一性。也就是说,接受一些(但是很小的)风险,你的字符串不会是唯一的。这是理解碰撞概率和熵有用的地方。
因此,我需要重复我的大胆假设,因为您需要一些具有较小重复风险的标识符。作为一个具体的例子,让我们说你需要500万个ID,其重复风险不到1万亿。那么你需要多长的弦?那么,这个问题是不明确的,因为它取决于使用的字符。但更重要的是,它被误导了。你需要的是字符串熵的规范,而不是它们的长度。
这是EntropyString可以提供帮助的地方。
Bits = entropy_string:bits(5.0e6, 1.0e12).
83.37013046707142
entropy_string:random_string(Bits).
<<"QDrjGQFGgGjJ4t9r2">>
还有其他预定义的字符集,您也可以指定自己的字符(虽然出于效率原因,仅支持2个字符的幂集)。最重要的是,在指定数量的字符串中重复的风险是明确的。不再猜测字符串长度。
答案 4 :(得分:1)
randchar(N) ->
randchar(N, []).
randchar(0, Acc) ->
Acc;
randchar(N, Acc) ->
randchar(N - 1, [random:uniform(26) + 96 | Acc]).
答案 5 :(得分:0)
您可以从此处使用函数uef_bin:random_latin_binary/2
:
https://github.com/DOBRO/uef-lib#uef_binrandom_latin_binary2
Bin = uef_bin:random_latin_binary(Length, any)
然后,如果您需要string()
类型:
String = erlang:binary_to_list(Bin)