tags:

views:

262

answers:

7

How can I get the first character in a string using Ruby?

Ultimately what I'm doing is taking someone's last name and just creating an initial out of it.

So if the string was "Smith" I just want "S".

A: 
>> s = 'Smith'                                                          
=> "Smith"                                                              
>> s[0]                                                                 
=> "S"                                                        
SilentGhost
note that this only works in ruby19. in ruby18 `"Smith"[0]` would return the integer value of the character 'S'. Both versions obey `"Smith"[0,1] == "S"`.
rampion
@rampion: indeed. I'd add that `"Smith"[0] == ?S` is true on both Ruby 1.8 and 1.9
Marc-André Lafortune
+4  A: 

If you use a recent version of Ruby (1.9.0 or later), the following should work:

'Smith'[0] # => 'S'

If you use either 1.9.0+ or 1.8.7, the following should work:

'Smith'.chars.first # => 'S'

If you use a version older than 1.8.7, this should work:

'Smith'.split(//).first # => 'S'

Note that 'Smith'[0,1] does not work on 1.8, it will not give you the first character, it will only give you the first byte.

Jörg W Mittag
note that this only works in ruby19. in ruby18 `"Smith"[0]` would return the integer value of the character 'S'. Both versions obey `"Smith"[0,1] == "S"`.
rampion
@rampion: Sure, but there's no indication in the question that the OP doesn't use the most recent version, so why bother complicating things?
Jörg W Mittag
I agree with Jörg. No need to answer questions for legacy software unless otherwise specified.
macek
Ruby 1.8 is not legacy! The Ruby 1.8 line is still supported and there will most likely be a 1.8.8 version released. Moreover, neither JRuby nor Rubinius yet support 1.9.I would bet 5$ that there are today far more users of 1.8 than 1.9.
Marc-André Lafortune
@Marc-Andre Lafortune: given that every single solution given for Ruby 1.8 on this page, including the accepted one and the highest voted one *do not actually work*, it seems likely that neither the person who asked the question nor the people who answered it, are actually running 1.8 or they would have caught it during testing. I agree that most *users* are running 1.8, but this is not a user, this is a *learner* who literally just downloaded Ruby an hour ago. He doesn't have a legacy application, he doesn't depend on third-party libraries. There would be no reason for him not to use 1.9.1.
Jörg W Mittag
`'Smith'[0,1]` gave "S" on Ruby 1.8.6 on my machine just now, and that's the answer I'd have given for that version. `'Smith'[0]` gives 83, which is what I'd expect per Pickaxe 2...
Mike Woodhouse
@Jörg: The answer `"Smith"[0,1]` does work on 1.8 (assuming ASCII). Not sure why you assume so much about the requester, as well as about everybody else who would like to learn from that question. For example, Mac OS X comes bundled with Ruby 1.8, so no installation is required for these users.
Marc-André Lafortune
How would you get the initial of the name 'Ångström' (in UTF-8) so that it would work as expected in both Ruby 1.8.x and 1.9.x? Neither of the suggested methods would work in 1.8.x.
Lars Haugseth
A: 

The regex /^([a-zA-Z])/ will return the first letter.

drewk
the regexp /^./ it's better to return first element.
shingara
The regex of /^./ matches any character and the OP said he wanted the first letter for an initial. If the first character -- no matter what -- is desired, you do not need a regex.
drewk
Interesting point about letter vs. character. Are there any use cases where you might get a character *other than* a letter, and you'd want to skip it in favor of a letter?
Brandon
There are certainly names out there that break our standard expectations, but are there any names that start with a character other than a letter? If so, would you want the first letter or the first character? I can think of several unusual examples of names: 1. mixed case: McDonald, 2. containing apostrophes: O'Donnell, 3. containing spaces inside name: Van Louwen, 4. starting out lower case: della Porta, 5. and using non-ASCII characters Ætna. In the case of a non-ASCII character, I assume you'd still want to use that as the initial.
Brandon
How about leading white space if any? In this case, /^\s*([a-zA-Z])/ will get the first character. If this is the return from user input, you need to validate that the user typed a character. User are always trying to crash your program ya know.... ;-} If you want to get the first alpha character, and validate in one step, use a regex. If you just want the first character without caring what it is, don't use a regex at all -- there are other methods that are faster. The regex of /^./ is wrong because it is a regex that does nothing but get the first character without validating the class...
drewk
Yes of course you need to validate user input, but validation on the name should be done when the user inputs the name, not when you are getting the initial from the name.
Brandon
+7  A: 

You can use Ruby's open classes to make your code much more readable. For instance, this:

class String
  def initial
    self[0,1]
  end
end

will allow you to use the initial method on any string. So if you have the following variables:

last_name = "Smith"
first_name = "John"

Then you can get the initials very cleanly and readably:

puts first_name.initial   # prints J
puts last_name.initial    # prints S

The other method mentioned here doesn't work on Ruby 1.8:

puts 'Smith'[0]           # prints 83

Of course, if you're not doing it on a regular basis, then defining the method might be overkill, and you could just do it directly:

puts last_name[0,1] 
Brandon
+1  A: 

Because of an annoying design choice in Ruby before 1.9 — some_string[0] returns the character code of the first character — the most portable way to write this is some_string[0,1], which tells it to get a substring at index 0 that's 1 character long.

Chuck
str[0,1] doesn't work the same in 1.8 and 1.9 either, as in the former it returns the first *byte* while in the latter it returns the first *character*.
Lars Haugseth
That's not really a difference in how the indexing works so much as in 1.9's support for multibyte languages. They're both meant to return the first character, but 1.8 has a more naive view of what a "character" is.
Chuck
A: 
"Smith"[0..0]

works in both ruby 1.8 and ruby 1.9.

Andrew Grimm
+2  A: 

In MRI 1.8.7 or greater:

'foobarbaz'.each_char.first
Wayne Conrad