Подтвердить что ты не робот

Как создать случайную буквенно-цифровую строку с помощью Erlang?

Я пытаюсь создать случайный буквенно-цифровой идентификатор с Erlang. Я наивно пробовал crypto:strong_rand_bytes(Bytes) генерировать случайный двоичный файл, а затем использовал этот двоичный файл, который был создан с помощью <<"my_unique_random_id">> - который не работал, потому что случайные биты не обязательно являются допустимой строкой UTF-8, правильно?

Ну, я искал другие варианты в документах erlang и в других местах, но ничего не нашел. Может ли кто-нибудь указать мне на решение?

4b9b3361

Ответ 1

Это может зависеть от случайности, в которой вы нуждаетесь. Erlang crypto Модуль производит сильные случайные данные, чем модуль random (смотрите также [Эрл-вопросы] Yaws безопасности бдительные - Yaws 1,93 и этот вопрос). Если вы хотите использовать strong_rand_bytes для генерации идентификатора, возможно, получить его base64 может быть достаточно:

> base64:encode(crypto:strong_rand_bytes(Bytes)).

В случае необходимости вы можете включить это в список.

Ответ 2

Согласно Генерация случайных строк в Erlang, для генерации строки определенной длины из определенного набора символов требуется всего несколько строк Erlang.

get_random_string(Length, AllowedChars) ->
    lists:foldl(fun(_, Acc) ->
                        [lists:nth(random:uniform(length(AllowedChars)),
                                   AllowedChars)]
                            ++ Acc
                end, [], lists:seq(1, Length)).

Сообщение в блоге содержит поэтапное объяснение кода. Посмотрите на комментарии для нескольких советов по оптимизации.

Ответ 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)
  ).

Ответ 4

Проблема с ответами на различные вопросы "Мне нужны случайные строки" (на любом языке) - это почти все решения, использующие неверную спецификацию, а именно длину строки. Сами вопросы редко показывают, почему нужны случайные строки, но я смело предполагаю, что они должны использоваться в качестве идентификаторов, которые должны быть уникальными.

Существует два ведущих способа получить строго уникальные строки: детерминистически (что не случайно) и хранить/сравнивать (что является обременительным). Что делать? Отбросьте призрак. Идите с вероятностной уникальностью. То есть, примите, что есть (хотя и небольшой) риск того, что ваши строки не будут уникальными. Здесь полезно понимание вероятности столкновения и энтропии.

Поэтому я перефразирую свое смелое предположение, поскольку вам нужно некоторое количество идентификаторов с небольшим риском повторения. В качестве конкретного примера предположим, что вам нужно 5 миллионов идентификаторов с риском повторения менее 1 триллиона. Итак, какая длина строки вам нужна? Ну, этот вопрос указан ниже, поскольку он зависит от используемых символов. Но что более важно, он ошибался. Вам нужна спецификация энтропии строк, а не их длина.

Здесь EntropyString может помочь.

Bits = entropy_string:bits(5.0e6, 1.0e12).
83.37013046707142
entropy_string:random_string(Bits).
<<"QDrjGQFGgGjJ4t9r2">>

Существуют и другие предопределенные наборы символов, и вы можете также указать свои собственные символы (хотя по соображениям эффективности поддерживаются только наборы с полномочиями в 2 символа). И, самое главное, риск повторения в указанном числе строк является явным. Больше не догадывается длина строки.

Ответ 5

randchar(N) ->
   randchar(N, []).

randchar(0, Acc) ->
   Acc;
randchar(N, Acc) ->
   randchar(N - 1, [random:uniform(26) + 96 | Acc]).

Ответ 6

Вы можете использовать функцию 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)