Đối lập với chr () trong Ruby là gì?


100

Trong nhiều ngôn ngữ, có một cặp hàm chr()ord()chuyển đổi giữa các số và giá trị ký tự. Trong một số ngôn ngữ, ord()được gọi là asc().

Ruby có Integer#chr, hoạt động tuyệt vời:

>> 65.chr
A

Đủ công bằng. Nhưng làm thế nào để bạn đi theo con đường khác?

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

bản in:

65

và điều đó khá gần với những gì tôi muốn. Nhưng tôi thực sự muốn tránh một vòng lặp - tôi đang tìm kiếm thứ gì đó đủ ngắn để có thể đọc được khi khai báo a const.

Câu trả lời:


84

Nếu Chuỗi # ord không tồn tại trong 1.9, nó tồn tại trong 2.0:

"A".ord #=> 65

33

Trong Ruby lên đến và bao gồm cả dòng 1.8, cả hai dòng sau sẽ tạo ra 65 (cho ASCII):

puts ?A
'A'[0]

Hành vi đã thay đổi trong Ruby 1.9, cả hai điều trên sẽ tạo ra "A" thay thế. Cách chính xác để làm điều này trong Ruby 1.9 là:

'A'[0].ord

Thật không may, ordphương thức này không tồn tại trong Ruby 1.8.


Thật không may là cách "đúng" trong Ruby 1.9 quá dài, nhưng ít nhất nó sẽ hiển thị dễ dàng hơn trong các tìm kiếm cho "ord". Cảm ơn câu trả lời rất chi tiết của bạn.
RJHunter

13

Thử:

'A'.unpack('c')

1
Bây giờ Ruby 1.9 đã thay đổi ý nghĩa của 'A' [0], đây là phương thức linh hoạt hơn.
AShelly

10

Tôi muốn +1 dylanfm và nhận xét của AShelly nhưng thêm [0]:

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

Lời gọi giải nén trả về một Mảng chứa một số nguyên duy nhất, không phải lúc nào cũng được chấp nhận khi muốn một số nguyên:

$ ruby ​​-e 'printf ("0x% 02X \ n", "A" .unpack ("C"))'
-e: 1: trong `printf ': không thể chuyển Mảng thành Số nguyên (TypeError)
    từ -e: 1
$ ruby ​​-e 'printf ("0x% 02X \ n", "A" .unpack ("C") [0])'
0x41
$ 

Tôi đang cố gắng viết mã hoạt động trên Ruby 1.8.1, 1.8.7 và 1.9.2.

Đã chỉnh sửa để chuyển C để giải nén bằng chữ hoa, vì unpack ("c") cho tôi -1 trong đó ord () cho tôi 255 (mặc dù chạy trên nền tảng mà ký tự của C được ký).


4

Vừa mới bắt gặp điều này khi đang tập hợp một phiên bản Ruby thuần túy của Stringprep thông qua RFC.

Cẩn thận với chrlỗi bên ngoài [0,255], thay vào đó hãy sử dụng thay thế di động 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)>

Cảm ơn bạn, điều này dường như là câu trả lời duy nhất mà cung cấp cho charvà nghịch đảo của nó trong trường hợp unicode một cách chính xác
Munyari

3

Ngoài ra, nếu bạn có ký tự trong một chuỗi và bạn muốn giải mã nó mà không cần vòng lặp:

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



2

Nếu bạn không ngại kéo các giá trị ra khỏi một mảng, bạn có thể sử dụng "A".bytes


0

Tôi đang viết mã cho 1.8.6 và 1.9.3 và tôi không thể nhận được bất kỳ giải pháp nào trong số này để hoạt động trong cả hai môi trường :(

Tuy nhiên, tôi đã tìm thấy một giải pháp khác: http://smajnr.net/2009/12/ruby-1-8-nomethoderror-undefined-method-ord-for-string.html

Điều đó cũng không hiệu quả với tôi nhưng tôi đã điều chỉnh nó để sử dụng:

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

Sau khi thực hiện điều đó, thì điều sau sẽ hoạt động trong cả hai môi trường

'A'[0].ord


Khi user18096 viết câu trả lời của họ "A".unpack("C")[0], đó là nhắm mục tiêu đến Ruby 1.8.1, Ruby 1.8.7 và Ruby 1.9.2. Nó có thất bại trong môi trường của bạn không? Những loại thất bại?
RJHunter

Xin chào RJHunter, tôi đang cố gắng chuyển đổi một ký tự cụ thể trong một chuỗi thành giá trị số của nó. Đoạn mã sau hoạt động trong 1.9.3 nhưng không hoạt động trong 1.8.6. self.status = tagAccountString[4].unpack('C')[0] Trong 1.8.6 tôi nhận được Exception undefined method giải nén '0: Fixnum xử lý dữ liệu thẻ đệm chính - exit` Các công trình đoạn mã sau (với giải pháp đề xuất của tôi) trong cả hai môi trường self.status = tagAccountString[4].ord có lời khuyên nào (ví dụ như một giải pháp tốt hơn) là chào đón nhiều hơn
hantscolin

tagAccountString[4]trả về một Chuỗi trong Hồng ngọc mới hơn nhưng được sử dụng để trả về một Fixnum trong Ruby 1.8. Đó là lý do tại sao bạn thấy lỗi , undefined method unpack for 0:Fixnum. Bạn có thể sử dụng status = tagAccountString[4,1].unpack('C')[0]hoặc thậm chí status, = tagAccountString.unpack('xxxxC')nếu bạn luôn muốn bỏ qua bốn ký tự và chuyển đổi ký tự tiếp theo.
RJHunter

Cảm ơn RJHunter về lời giải thích và các giải pháp thay thế. Tuy nhiên, như "tôi" Giải pháp là dễ đọc hơn và tái sử dụng, tôi sẽ gắn bó với điều đó (trừ khi có một lý do chính đáng không phải là quá?)
hantscolin
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.