C # содержит метод для генерации Guid из байтов:

byte[] bytes = {107, 97, 155, 242, 36, 52, 182, 87, 67, 223, 163, 166, 7, 175, 123, 223};
Guid guid = new Guid(bytes); // => {f29b616b-3424-57b6-43df-a3a607af7bdf}

Как написать код ruby, который будет генерировать тот же uuid, что и в C #? Uuid, определенный в Ruby: SecureRandom didn не принимаю никаких параметров.

0
jing 2 Мар 2018 в 13:38

4 ответа

Лучший ответ

Еще один способ снять шкуру с кошки, простой и понятный:

a = [107, 97, 155, 242, 36, 52, 182, 87, 67, 223, 163, 166, 7, 175, 123, 223]

def _guid(ints, reverse=false)
  hexes = ints.map { |b| b.to_s(16).rjust(2, '0') }
  return hexes.reverse.join if reverse
  hexes.join
end

def guid(ints)
  '%s-%s-%s-%s-%s' % [
    _guid(ints[0...4], true),
    _guid(ints[4...6], true),
    _guid(ints[6...8], true),
    _guid(ints[8...10]),
    _guid(ints[10..-1]),
  ]
end

puts guid a # => f29b616b-3424-57b6-43df-a3a607af7bdf
1
Harsh Gupta 3 Мар 2018 в 02:30

Ответ в первом приближении:

a = [107, 97, 155, 242, 36, 52, 182, 87, 67, 223, 163, 166, 7, 175, 123, 223]
ah = a.map{ |i| i.to_s(16) }

puts [4,2,2,2,6].inject([]) { |result, idx| result << ah.slice!(0, idx).reverse.join }.join("-")

f29b616b-3424-57b6-df43-df7baf7a6a3
=> nil

Почти наверняка есть более чистый способ сделать это, но это дает вам кое-что для работы. Он использует inject для накопления сгенерированных секций uuid-строк в массив, а затем объединяет их в guid.

Каждый блок guid является подмассивом байтового массива, вроде бы упорядоченного от lsb до msb.

-1
mcfinnigan 2 Мар 2018 в 11:51

Вот один из способов, используя только sprintf. Я не уверен, люблю ли я это или ненавижу это.

arr = [107, 97, 155, 242, 36, 52, 182, 87, 67, 223, 163, 166, 7, 175, 123, 223]

fmt = "%4$02x%3$02x%2$02x%1$02x-" \
      "%6$02x%5$02x-%8$02x%7$02x-%9$02x%10$02x-" \
      "%11$02x%12$02x%13$02x%14$x%15$x%16$x"

str = sprintf(fmt, *arr)
# => "f29b616b-3424-57b6-43df-a3a607af7bdf"

При этом используется флаг sprintf $ для явного указания порядка шестнадцатеричных цифр, например, %4$02x означает «вывести четвертый октет в аргументах в виде двух шестнадцатеричных цифр».

Мы могли бы, конечно, сгенерировать строку формата:

positions = [[4, 3, 2, 1], [6, 5], [8, 7], [9, 10], 11..16]
fmt = positions.map {|a| a.map {|d| "%#{d}$02x" }.join }.join("-")
# => "%4$02x%3$02x%2$02x%1$02x-%6$02x%5$02x-%8$02x%7$02x-%9$02x%10$02x-%11$02x%12$02x%13$02x%14$02x%15$02x%16$02x"

str = sprintf(fmt, *arr)
# => "f29b616b-3424-57b6-43df-a3a607af7bdf"

... но в этот момент вы могли бы просто сделать это:

positions = [ [ 3, 2, 1, 0 ], [ 5, 4 ], [ 7, 6 ], [ 8, 9 ], 10..15 ]
str = positions.map {|a| a.map {|n| "%02x" % arr[n] }.join }.join("-")
# => f29b616b-3424-57b6-43df-a3a607af7bdf

Вы можете увидеть все это в действии на сайте repl.it: https://repl.it/@jrunning/FamousRewardingApplescript

2
Jordan Running 2 Мар 2018 в 17:16

Иногда процесс разработки включает в себя написание кода, а не только вызов существующих библиотек:

bytes.each_with_object([]) do |b, acc|
  acc << [] if acc.size == 0 ||
               acc.size == 1 && acc.last.size == 4 ||
               acc.size > 1 && acc.size < 5 && acc.last.size == 2
  acc.last << b.to_s(16).rjust(2, '0')
end.map.with_index do |e, idx|
  idx < 3 ? e.reverse : e
end.map(&:join).join('-')
#⇒ "f29b616b-3424-57b6-43df-a3a607af7bdf"
3
Aleksei Matiushkin 2 Мар 2018 в 11:51