60

I'm trying to produce some Ruby code that will take a string and return a new one, with a number x number of characters removed from its end - these can be actual letters, numbers, spaces etc.

Ex: given the following string

a_string = "a1wer4zx"

I need a simple way to get the same string, minus - say - the 3 last characters. In the case above, that would be "a1wer". The way I'm doing it right now seems very convoluted:

an_array = a_string.split(//,(a_string.length-2))
an_array.pop
new_string = an_array.join

Any ideas?

nanosoft
  • 2,913
  • 4
  • 41
  • 61
wotaskd
  • 925
  • 1
  • 10
  • 15
  • 5
    It is convoluted, and, it's good that you had that feeling. Ruby in whole is an elegant language so when it feels like you're having to jump through hoops to do something, it's a warning you are probably going about it the wrong way. Of course there are going to be times that the solution is inelegant, because that's the nature of programming. Still, good Ruby really is zen-like, so go with the flow. :-) – the Tin Man Dec 24 '10 at 23:25

6 Answers6

126

How about this?

s[0, s.length - 3]

Or this

s[0..-4]

edit

s = "abcdefghi"
puts s[0, s.length - 3]  # => abcdef
puts s[0..-4]            # => abcdef
Nikita Rybak
  • 67,365
  • 22
  • 157
  • 181
16

Use something like this:

s = "abcdef"
new_s = s[0..-2] # new_s = "abcde"

See the slice method here: http://ruby-doc.org/core/classes/String.html

Brian Clapper
  • 25,705
  • 7
  • 65
  • 65
8

Another option could be to use the slice method

a_string = "a1wer4zx"
a_string.slice(0..5) 
=> "a1wer4"   

Documentation: http://ruby-doc.org/core-2.5.0/String.html#method-i-slice

Paulo Fidalgo
  • 21,709
  • 7
  • 99
  • 115
3

if you need it in rails you can use first (source code)

s = '1234567890'
x = 4
s.first(s.length - x) # => "123456"

there is also last (source code)

s.last(2) # => "90"

alternatively check from/to

Aray Karjauv
  • 2,679
  • 2
  • 26
  • 44
2

Another option is getting the list of chars of the string, takeing x chars and joining back to a string:

[13] pry(main)> 'abcdef'.chars.take(2).join
=> "ab"
[14] pry(main)> 'abcdef'.chars.take(20).join
=> "abcdef"
Leo Brito
  • 2,053
  • 13
  • 20
1

I know a lot of people already said this, but I think the best option is this:

'abcdefg'[0..-4] # should return 'abcd'

Something important to realize is that the returned string is inclusive on both endpoints. A lot of string parsing methods (e.g., the java and javascript substring method) are inclusive on the first endpoint and exclusive on the last, but this is NOT the case with the above way.

'abcdefghijklm'[1..5] # returns 'bcdef'


// substring method in java or javascript returns 'bcde'

'abcdefghijklm'.substring(1, 5);