Как сгенерировать случайную строку в Ruby - PullRequest
710 голосов
/ 18 сентября 2008

В настоящее время я генерирую 8-символьную псевдослучайную строку в верхнем регистре для "A" .. "Z":

value = ""; 8.times{value  << (65 + rand(25)).chr}

но он не выглядит чистым и не может быть передан в качестве аргумента, поскольку это не одно утверждение. Чтобы получить строку со смешанным регистром "a" .. "z" плюс "A" .. "Z", я изменил ее на:

value = ""; 8.times{value << ((rand(2)==1?65:97) + rand(25)).chr}

но это похоже на мусор.

У кого-нибудь есть лучший метод?

Ответы [ 51 ]

5 голосов
/ 20 июня 2011

Я думаю, это хороший баланс краткости, ясности и простоты модификации.

characters = ('a'..'z').to_a + ('A'..'Z').to_a
# Prior to 1.9, use .choice, not .sample
(0..8).map{characters.sample}.join

Легко модифицируется

Например, включая цифры:

characters = ('a'..'z').to_a + ('A'..'Z').to_a + (0..9).to_a

Верхний регистр шестнадцатеричный:

characters = ('A'..'F').to_a + (0..9).to_a

Для действительно впечатляющего набора символов:

characters = (32..126).to_a.pack('U*').chars.to_a
4 голосов
/ 18 сентября 2015

Это решение нуждается во внешней зависимости, но кажется более привлекательным, чем другое.

  1. Установить гем Фейкер
  2. Faker::Lorem.characters(10) # => "ang9cbhoa8"
4 голосов
/ 20 апреля 2011

Дано:

chars = [*('a'..'z'),*('0'..'9')].flatten

Одиночное выражение, может быть передано в качестве аргумента, допускает дублирование символов:

Array.new(len) { chars.sample }.join
4 голосов
/ 28 ноября 2013

Мой любимый это (:A..:Z).to_a.shuffle[0,8].join. Обратите внимание, что для перемешивания требуется Ruby> 1,9.

3 голосов
/ 04 октября 2011
''.tap {|v| 4.times { v << ('a'..'z').to_a.sample} }
3 голосов
/ 03 декабря 2013

Я просто пишу маленький камень random_token, чтобы генерировать случайные токены для большинства случаев использования, наслаждайтесь ~

https://github.com/sibevin/random_token

3 голосов
/ 03 мая 2012

Мои 2 цента:

  def token(length=16)
    chars = [*('A'..'Z'), *('a'..'z'), *(0..9)]
    (0..length).map {chars.sample}.join
  end
3 голосов
/ 08 августа 2010

Недавно я делал что-то подобное, чтобы сгенерировать 8-байтовую случайную строку из 62 символов. Символы были 0-9, a-z, A-Z. У меня был их массив, так как я делал 8 циклов и выбирал случайное значение из массива. Это было внутри приложения rails.

str = '' 8.times {|i| str << ARRAY_OF_POSSIBLE_VALUES[rand(SIZE_OF_ARRAY_OF_POSSIBLE_VALUES)] }

Странная вещь в том, что я получил много дубликатов. Теперь случайно это почти никогда не должно происходить. 62 ^ 8 огромен, но из 1200 или около того кодов в БД у меня было много дубликатов. Я заметил, что они происходят на часовых границах друг друга. Другими словами, в 12:12:23 и 2:12:22 я мог бы увидеть дуплекс или что-то в этом роде ... не уверен, является ли время проблемой или нет.

Этот код был до создания объекта activerecord. Перед созданием записи этот код запускается и генерирует «уникальный» код. Записи в БД всегда создавались надежно, но код (стр. В строке выше) дублировался слишком часто.

Я создал сценарий для выполнения 100000 итераций этой строки с небольшой задержкой, поэтому потребуется 3-4 часа в надежде увидеть какой-то шаблон повторения на почасовой основе, но ничего не увидел. Я понятия не имею, почему это происходило в моем приложении rails.

2 голосов
/ 22 февраля 2011

попробуйте это

def rand_name(len=9)
  ary = [('0'..'9').to_a, ('a'..'z').to_a, ('A'..'Z').to_a]
  name = ''

  len.times do
    name << ary.choice.choice
  end
  name
end

Мне нравятся ответы в этой ветке, они мне очень помогли! это просто не кажется мне правильным, так как у нас есть метод выбора Array # в этом отношении.

2 голосов
/ 24 августа 2011

Вот еще один метод:

  • Он использует безопасный генератор случайных чисел вместо rand ()
  • Может использоваться в URL и именах файлов
  • Содержит прописные, строчные буквы и цифры
  • Имеет возможность не включать неоднозначные символы I0l01

Необходимо require "securerandom"

def secure_random_string(length = 32, non_ambiguous = false)
  characters = ('a'..'z').to_a + ('A'..'Z').to_a + ('0'..'9').to_a

  %w{I O l 0 1}.each{ |ambiguous_character| 
    characters.delete ambiguous_character 
  } if non_ambiguous

  (0...length).map{
    characters[ActiveSupport::SecureRandom.random_number(characters.size)]
  }.join
end
...