Що протилежне chr () у Ruby?


100

У багатьох мовах є пара функцій chr()і ord(), які перетворюють між числами та значеннями символів. У деяких мовах ord()називається asc().

Ruby має Integer#chr, що чудово працює:

>> 65.chr
A

Досить справедливо. Але як ви йдете іншим шляхом?

"A".each_byte do |byte|
   puts byte
end

відбитки:

65

і це досить близько до того, що я хочу. Але я дійсно вважаю за краще уникати циклу - я шукаю щось досить коротке, яке можна прочитати при оголошенні а const.

Відповіді:



33

У Ruby до і включаючи серії 1.8, наступне буде виробляти 65 (для ASCII):

puts ?A
'A'[0]

Поведінка змінилася в Ruby 1.9, і те, і інше буде замість цього створювати "A". Правильний спосіб зробити це в Ruby 1.9:

'A'[0].ord

На жаль, ordметод не існує в Ruby 1.8.


Прикро, що "правильний" шлях у Ruby 1.9 настільки довгий, але, принаймні, він виявиться легшим у пошуку "ord". Дякую за дуже детальну відповідь.
RJHunter

13

Спробуйте:

'A'.unpack('c')

1
Тепер, коли Ruby 1.9 змінив значення "A" [0], це більш портативний метод.
AShelly

10

Я хотів би поставити +1 до коментаря dylanfm та коментаря AShelly, але додати [0]:

'A'.unpack('C')[0]

Розпаковується виклик повертає масив, що містить одне ціле число, яке не завжди приймається там, де потрібне ціле число:

$ ruby ​​-e 'printf ("0x% 02X \ n", "A" .unpack ("C"))'
-e: 1: у `printf ': не вдається перетворити масив у цілий (TypeError)
    від -е: 1
$ ruby ​​-e 'printf ("0x% 02X \ n", "A" .unpack ("C") [0])'
0x41
$ 

Я намагаюся написати код, який працює на Ruby 1.8.1, 1.8.7 та 1.9.2.

Відредаговано, щоб передати C, щоб розпакувати великі регістри, тому що unpack ("c") дає мені -1, де ord () дає мені 255 (незважаючи на те, що я працюю на платформі, де підписано знак char).


4

Щойно натрапив на це, збираючи чисту Ruby-версію Stringprep через RFC.

Остерігайтеся того, що chrне виходить ззовні [0,255], замість цього використовуйте портативні заміни 1.9.x - 2.1.x:

[22] pry(main)> "\u0221".ord.chr
RangeError: 545 out of char range
from (pry):2:in 'chr'
[23] pry(main)> x = "\u0221".unpack('U')[0]
=> 545
[24] pry(main)> [x].pack('U')
=> "ȡ"
[25] pry(main)>

Дякую, це, здається, єдина відповідь, яка дає charта його зворотний випадок у випадку Unicode правильно
Munyari

3

Крім того, якщо у вас є char в рядку, і ви хочете розшифрувати його без циклу:

puts 'Az'[0]
=> 65
puts 'Az'[1]
=> 122



2

Якщо ви не проти витягнути значення з масиву, можете скористатися "A".bytes


0

Я пишу код для 1.8.6 та 1.9.3, і мені не вдалося змусити жодне з цих рішень працювати в обох середовищах :(

Однак я натрапив на інше рішення: http://smajnr.net/2009/12/ruby-1-8-nomethoderror-undefined-method-ord-for-string.html

Це не працювало і для мене, але я адаптував його для мого використання:

unless "".respond_to?(:ord)
  class Fixnum
    def ord
      return self
    end
  end
end

Зробивши це, наступне буде працювати в обох середовищах

'A'[0].ord


Коли user18096 написав свою відповідь, "A".unpack("C")[0]він орієнтувався на Ruby 1.8.1, Ruby 1.8.7 та Ruby 1.9.2. Невдача у вашому оточенні? Яка невдача?
RJHunter

Привіт RJHunter, я намагаюся перетворити певний символ у рядку в його числове значення. Наступний код працює в 1.9.3, але не 1.8.6. self.status = tagAccountString[4].unpack('C')[0] У 1.8.6 я Exception undefined method розпаковую "за 0: Fixnum обробляє основні дані буферизованих тегів - вихід". Наступний код працює (з моїм запропонованим рішенням) в обох середовищах. self.status = tagAccountString[4].ord Будь-яка порада (наприклад, краще рішення) є більш ніж вітаю
hantscolin

tagAccountString[4]повертає String у новіших рубінах, але використовується для повернення Fixnum у Ruby 1.8. Ось чому ви помітили помилку, undefined method unpack for 0:Fixnum. Ви можете використовувати status = tagAccountString[4,1].unpack('C')[0]або навіть status, = tagAccountString.unpack('xxxxC')якщо завжди хочете ігнорувати чотири символи та перетворювати наступний.
RJHunter

Дякую RJHunter за пояснення та альтернативні рішення. Однак, оскільки "моє" рішення є більш читабельним і багаторазовим, я дотримуватимусь цього (якщо не є теж вагомих причин?)
hantscolin
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.