Ruby, remove last N characters from a string?

RubyString

Ruby Problem Overview


What is the preferred way of removing the last n characters from a string?

Ruby Solutions


Solution 1 - Ruby

irb> 'now is the time'[0...-4]
=> "now is the "

Solution 2 - Ruby

If the characters you want to remove are always the same characters, then consider chomp:

'abc123'.chomp('123')    # => "abc"

The advantages of chomp are: no counting, and the code more clearly communicates what it is doing.

With no arguments, chomp removes the DOS or Unix line ending, if either is present:

"abc\n".chomp      # => "abc"
"abc\r\n".chomp    # => "abc"

From the comments, there was a question of the speed of using #chomp versus using a range. Here is a benchmark comparing the two:

require 'benchmark'

S = 'asdfghjkl'
SL = S.length
T = 10_000
A = 1_000.times.map { |n| "#{n}#{S}" }

GC.disable

Benchmark.bmbm do |x|
  x.report('chomp') { T.times { A.each { |s| s.chomp(S) } } }
  x.report('range') { T.times { A.each { |s| s[0...-SL] } } }
end

Benchmark Results (using CRuby 2.13p242):

Rehearsal -----------------------------------------
chomp   1.540000   0.040000   1.580000 (  1.587908)
range   1.810000   0.200000   2.010000 (  2.011846)
-------------------------------- total: 3.590000sec

            user     system      total        real
chomp   1.550000   0.070000   1.620000 (  1.610362)
range   1.970000   0.170000   2.140000 (  2.146682)

So chomp is faster than using a range, by ~22%.

Solution 3 - Ruby

Ruby 2.5+

As of Ruby 2.5 you can use delete_suffix or delete_suffix! to achieve this in a fast and readable manner.

The docs on the methods are here.

If you know what the suffix is, this is idiomatic (and I'd argue, even more readable than other answers here):

'abc123'.delete_suffix('123')     # => "abc"
'abc123'.delete_suffix!('123')    # => "abc"

It's even significantly faster (almost 40% with the bang method) than the top answer. Here's the result of the same benchmark:

                     user     system      total        real
chomp            0.949823   0.001025   0.950848 (  0.951941)
range            1.874237   0.001472   1.875709 (  1.876820)
delete_suffix    0.721699   0.000945   0.722644 (  0.723410)
delete_suffix!   0.650042   0.000714   0.650756 (  0.651332)

I hope this is useful - note the method doesn't currently accept a regex so if you don't know the suffix it's not viable for the time being. However, as the accepted answer (update: at the time of writing) dictates the same, I thought this might be useful to some people.

Solution 4 - Ruby

str = str[0...-n]

Solution 5 - Ruby

I would suggest chop. I think it has been mentioned in one of the comments but without links or explanations so here's why I think it's better:

It simply removes the last character from a string and you don't have to specify any values for that to happen.

If you need to remove more than one character then chomp is your best bet. This is what the ruby docs have to say about chop:

> Returns a new String with the last character removed. If the string > ends with \r\n, both characters are removed. Applying chop to an empty > string returns an empty string. String#chomp is often a safer > alternative, as it leaves the string unchanged if it doesn’t end in a > record separator.

Although this is used mostly to remove separators such as \r\n I've used it to remove the last character from a simple string, for example the s to make the word singular.

Solution 6 - Ruby

name = "my text"
x.times do name.chop! end

Here in the console:

>name = "Nabucodonosor"
 => "Nabucodonosor" 
> 7.times do name.chop! end
 => 7 
> name
 => "Nabuco" 

Solution 7 - Ruby

Dropping the last n characters is the same as keeping the first length - n characters.

Active Support includes String#first and String#last methods which provide a convenient way to keep or drop the first/last n characters:

require 'active_support/core_ext/string/access'

"foobarbaz".first(3)  # => "foo"
"foobarbaz".first(-3) # => "foobar"
"foobarbaz".last(3)   # => "baz"
"foobarbaz".last(-3)  # => "barbaz"

Solution 8 - Ruby

if you are using rails, try:

"my_string".last(2) # => "ng"

[EDITED]

To get the string WITHOUT the last 2 chars:

n = "my_string".size
"my_string"[0..n-3] # => "my_stri"

Note: the last string char is at n-1. So, to remove the last 2, we use n-3.

Solution 9 - Ruby

Solution 10 - Ruby

You can always use something like

 "string".sub!(/.{X}$/,'')

Where X is the number of characters to remove.

Or with assigning/using the result:

myvar = "string"[0..-X]

where X is the number of characters plus one to remove.

Solution 11 - Ruby

If you're ok with creating class methods and want the characters you chop off, try this:

class String
  def chop_multiple(amount)
    amount.times.inject([self, '']){ |(s, r)| [s.chop, r.prepend(s[-1])] }
  end
end

hello, world = "hello world".chop_multiple 5
hello #=> 'hello '
world #=> 'world'

Solution 12 - Ruby

Using regex:

str = 'string'
n = 2  #to remove last n characters

str[/\A.{#{str.size-n}}/] #=> "stri"

Solution 13 - Ruby

x = "my_test"
last_char = x.split('').last

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionJP SilvashyView Question on Stackoverflow
Solution 1 - RubyDigitalRossView Answer on Stackoverflow
Solution 2 - RubyWayne ConradView Answer on Stackoverflow
Solution 3 - RubySRackView Answer on Stackoverflow
Solution 4 - RubyNakilonView Answer on Stackoverflow
Solution 5 - RubykakubeiView Answer on Stackoverflow
Solution 6 - RubyjoscasView Answer on Stackoverflow
Solution 7 - RubychocolateboyView Answer on Stackoverflow
Solution 8 - RubyGuihenView Answer on Stackoverflow
Solution 9 - RubyCody CaughlanView Answer on Stackoverflow
Solution 10 - RubyZsolt BotykaiView Answer on Stackoverflow
Solution 11 - RubyBen AubinView Answer on Stackoverflow
Solution 12 - RubySagar PandyaView Answer on Stackoverflow
Solution 13 - RubyReshmi MitraView Answer on Stackoverflow