Was ist das Gegenteil von chr () in Ruby?


100

In vielen Sprachen gibt es zwei Funktionen chr()und ord(), die zwischen Zahlen und Zeichenwerten konvertieren. In einigen Sprachen ord()heißt asc().

Ruby hat Integer#chr, was super funktioniert:

>> 65.chr
A

Meinetwegen. Aber wie gehst du in die andere Richtung?

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

Drucke:

65

und das ist ziemlich nah an dem, was ich will. Aber ich würde eine Schleife wirklich lieber vermeiden - ich suche etwas, das kurz genug ist, um bei der Deklaration von a lesbar zu sein const.

Antworten:


84

Wenn String # ord in 1.9 nicht vorhanden war, ist dies in 2.0 der Fall:

"A".ord #=> 65

33

In Ruby bis einschließlich der 1.8-Serie werden beide 65 (für ASCII) produzieren:

puts ?A
'A'[0]

Das Verhalten hat sich in Ruby 1.9 geändert. Beide oben genannten Elemente erzeugen stattdessen "A". Der richtige Weg, dies in Ruby 1.9 zu tun, ist:

'A'[0].ord

Leider existiert die ordMethode in Ruby 1.8 nicht.


Es ist bedauerlich, dass der "richtige" Weg in Ruby 1.9 so lang ist, aber zumindest wird er bei der Suche nach "ord" leichter angezeigt. Vielen Dank für Ihre sehr detaillierte Antwort.
RJHunter

13

Versuchen:

'A'.unpack('c')

1
Nachdem Ruby 1.9 die Bedeutung von 'A' [0] geändert hat, ist dies die portablere Methode.
AShelly

10

Ich möchte +1 Dylanfm und AShellys Kommentar, aber füge die [0] hinzu:

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

Der Entpackungsaufruf gibt ein Array zurück, das eine einzelne Ganzzahl enthält. Dies wird nicht immer akzeptiert, wenn eine Ganzzahl gewünscht wird:

$ ruby ​​-e 'printf ("0x% 02X \ n", "A" .unpack ("C"))'
-e: 1: in `printf ': Array kann nicht in Integer konvertiert werden (TypeError)
    von -e: 1
$ ruby ​​-e 'printf ("0x% 02X \ n", "A" .unpack ("C") [0])'
0x41
$ 

Ich versuche, Code zu schreiben, der unter Ruby 1.8.1, 1.8.7 und 1.9.2 funktioniert.

Bearbeitet, um C zum Entpacken in Großbuchstaben zu übergeben, da Entpacken ("c") -1 ergibt, wobei ord () 255 ergibt (obwohl es auf einer Plattform ausgeführt wird, auf der Cs Zeichen signiert ist).


4

Ich bin gerade darauf gestoßen, als ich eine reine Ruby-Version von Stringprep über RFCs zusammengestellt habe.

chrBeachten Sie, dass dies außerhalb von [0,255] fehlschlägt. Verwenden Sie stattdessen tragbare Ersatzteile 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)>

Vielen Dank, dies scheint die einzige Antwort zu sein, die gibt charund ihre Umkehrung im Fall von Unicode richtig
Munyari

3

Wenn Sie das Zeichen in einer Zeichenfolge haben und es ohne Schleife dekodieren möchten:

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



2

Wenn es Ihnen nichts ausmacht, die Werte aus einem Array zu ziehen, können Sie verwenden "A".bytes


0

Ich schreibe Code für 1.8.6 und 1.9.3 und konnte keine dieser Lösungen in beiden Umgebungen zum Laufen bringen :(

Ich bin jedoch auf eine andere Lösung gestoßen : http://smajnr.net/2009/12/ruby-1-8-nomethoderror-undefined-method-ord-for-string.html

Das hat auch bei mir nicht funktioniert, aber ich habe es für meinen Gebrauch angepasst:

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

Nachdem dies geschehen ist, funktioniert das Folgende in beiden Umgebungen

'A'[0].ord


Als user18096 ihre Antwort schrieb "A".unpack("C")[0], zielte dies auf Ruby 1.8.1, Ruby 1.8.7 und Ruby 1.9.2 ab. Schlägt es in Ihrer Umgebung fehl? Was für ein Fehler?
RJHunter

Hallo RJHunter, ich versuche ein bestimmtes Zeichen in einer Zeichenfolge in seinen Zahlenwert umzuwandeln. Der folgende Code funktioniert in 1.9.3, jedoch nicht in 1.8.6. self.status = tagAccountString[4].unpack('C')[0] In 1.8.6 Exception undefined method entpacke ich 'für 0: Fixnum verarbeitet gepufferte Haupt-Tag-Daten - exit` Der folgende Code funktioniert (mit meiner vorgeschlagenen Lösung) in beiden Umgebungen. self.status = tagAccountString[4].ord Jeder Rat (z. B. eine bessere Lösung) ist mehr als willkommen
hantscolin

tagAccountString[4]Gibt einen String in neueren Rubinen zurück, wird jedoch verwendet, um ein Fixnum in Ruby 1.8 zurückzugeben. Deshalb haben Sie den Fehler gesehen undefined method unpack for 0:Fixnum. Sie können status = tagAccountString[4,1].unpack('C')[0]oder sogar verwenden, status, = tagAccountString.unpack('xxxxC')wenn Sie immer vier Zeichen ignorieren und das nächste konvertieren möchten.
RJHunter

Vielen Dank an RJHunter für die Erklärung und die alternativen Lösungen. Da "meine" Lösung jedoch besser lesbar und wiederverwendbar ist, bleibe ich dabei (es sei denn, es gibt nicht auch einen guten Grund?)
Hantscolin
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.