118

To get the last n characters from a string, I assumed you could use

ending = string[-n..-1]

but if the string is less than n letters long, you get nil.

What workarounds are available?

Background: The strings are plain ASCII, and I have access to ruby 1.9.1, and I'm using Plain Old Ruby Objects (no web frameworks).

Andrew Grimm
  • 78,473
  • 57
  • 200
  • 338

9 Answers9

124

Well, the easiest workaround I can think of is:

ending = str[-n..-1] || str

(EDIT: The or operator has lower precedence than assignment, so be sure to use || instead.)

perimosocordiae
  • 17,287
  • 14
  • 60
  • 76
  • +1... I think this way is easier to read than `string.reverse[0..n].reverse`, which gives me a second of "wait, why is he doing that?" (or would if I weren't reading it in the context of this question) – Arkaaito Feb 01 '10 at 05:19
  • 4
    Good answer, but it should be `||` instead of `or`, or put parentheses around `str[-n..-1] or str`. – Andrew Grimm Feb 01 '10 at 05:34
  • Good answer, but I don't like that ruby doesn't treat s[-inf..-1] the same as x[0..inf] – klochner Feb 01 '10 at 07:35
  • Thanks for noting the operator precedence issue, Andrew. Gets me every time. – perimosocordiae Feb 02 '10 at 08:21
  • @perimosocordiae you aren't the only one. http://stackoverflow.com/questions/372652/what-are-the-ruby-gotchas-a-newbie-should-be-warned-about – Andrew Grimm Feb 02 '10 at 22:06
  • I like this solution because [] is so flexible to operate on any position of string. – Donato Jul 21 '15 at 23:56
112

Here you have a one liner, you can put a number greater than the size of the string:

"123".split(//).last(5).to_s

For ruby 1.9+

"123".split(//).last(5).join("").to_s

For ruby 2.0+, join returns a string

"123".split(//).last(5).join
nostopbutton
  • 424
  • 5
  • 13
Gareve
  • 3,372
  • 2
  • 21
  • 23
74

In straight Ruby (without Rails), you can do

string.chars.last(n).join

For example:

2.4.1 :009 > a = 'abcdefghij'
 => "abcdefghij"
2.4.1 :010 > a.chars.last(5).join
 => "fghij"
2.4.1 :011 > a.chars.last(100).join
 => "abcdefghij"

If you're using Ruby on Rails, you can call methods first and last on a string object. These methods are preferred as they're succinct and intuitive.

For example:

[1] pry(main)> a = 'abcdefg'                                                                                                                
 => "abcdefg"
[2] pry(main)> a.first(3)                                                                                                                   
 => "abc"
[3] pry(main)> a.last(4)                                                                                                                    
 => "defg"
Zack Xu
  • 11,505
  • 9
  • 70
  • 78
14
ending = string.reverse[0...n].reverse
Andrew Grimm
  • 78,473
  • 57
  • 200
  • 338
  • This is the best approach I see on this page that satisfies the requirement of being able to supply an ending character length that exceeds the total string length. – Rob.Kachmar Aug 08 '13 at 18:46
  • 1
    For example, if you are intending to take the last 3 character of a group of stings like "abcde", "ab", and "a". This technique will result in "cde", "ab", and "a" using the same code for each. `"abcde".reverse[0,3].reverse` >>> "cde" `"ab".reverse[0,3].reverse` >>> "ab" `"a".reverse[0,3].reverse` >>> "a" – Rob.Kachmar Aug 08 '13 at 18:56
10

You can use the following code:

string[string.length-n,string.length]
enrico.bacis
  • 30,497
  • 10
  • 86
  • 115
rurkss
  • 113
  • 1
  • 4
  • 1
    code only - answers are not always helpful. explaining why/how this code is the fix would be great – ry8806 Jun 03 '15 at 12:04
6

To get the last n characters from a string, you could do this

a[-n, n] if a is the array.

Here's and example if you would want one.

ruby-1.9.2-p180 :006 > a = "911234567890"

=> "911234567890"

ruby-1.9.2-p180 :009 > a[-5,5]

=> "67890"

ruby-1.9.2-p180 :010 > a[-7,7]

=> "4567890"

Sunil
  • 3,424
  • 2
  • 24
  • 25
5

Have you tried a regex?

string.match(/(.{0,#{n}}$)/)
ending=$1

The regex captures as many characters it can at the end of the string, but no more than n. And stores it in $1.

EmFi
  • 23,435
  • 3
  • 57
  • 68
1

Improvement on EmFi's answer.

string[/.{,#{n}}\z/m]
sawa
  • 165,429
  • 45
  • 277
  • 381
1

For those who are using Ruby on Rails, you can simply do this:

str.last(n)

Note: I realize this doesn't answer the OP question because in PLAIN Ruby (w/o Rails) the last method does not exist for String. For that, there are many other good answers here.

Jeremy Moritz
  • 13,864
  • 7
  • 39
  • 43