【问题标题】:Ruby, remove last N characters from a string?Ruby,从字符串中删除最后 N 个字符?
【发布时间】:2011-05-11 16:44:26
【问题描述】:

从字符串中删除最后一个n 字符的首选方法是什么?

【问题讨论】:

  • 如果你知道后缀(最佳答案建议很多人来这里寻找这个),你可以使用 Ruby 2.5 中的delete_suffixMore info here.

标签: ruby string


【解决方案1】:
irb> 'now is the time'[0...-4]
=> "now is the "

【讨论】:

  • 请注意,这只适用于 Ruby 1.9。在 Ruby 1.8 中,这将删除最后的 bytes,而不是最后的 characters
  • 但如果他使用的是 1.8.x,他的意思可能是 "bytes"
  • 这确实有效,但我发现 'abc123'.chomp('123') 对短字符串和非常长字符串的速度都是两倍。 (Ruby 2.0.0-p247) 谁能证实这一点?
  • 对于那些想知道为什么这个特定示例不起作用的人......这里有 3 个点而不是 2 个点,即 [0...-4] 不是 [0..-4]
  • @Plamarob 我认为说 chomp 快 53 纳秒比说它快两倍更相关。然后,您可以更好地估计使用它的成本与价值,以及它是否可能是在给定情况下需要优化的东西。
【解决方案2】:

如果要删除的字符总是相同的字符,那么考虑chomp

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

chomp 的优点是:不用计数,代码更清楚地传达了它在做什么。

如果没有参数,chomp 会删除 DOS 或 Unix 行尾(如果存在):

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

在 cmets 中,存在使用 #chomp 与使用范围的速度问题。这是比较两者的基准:

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

基准测试结果(使用 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)

因此 chomp 比使用范围快约 22%。

【讨论】:

  • Chop 也是一种选择。删除的内容不那么挑剔了。
  • 我发现事实恰恰相反。现实情况是 .chomp 似乎始终快一倍。
  • @Plamarob,Ruby 中的基准测试常常令人惊讶。我经常犯错,以至于我不再试图猜测什么会更快。此外,如果基准结果可以改进答案,请随时编辑。
  • 如果我没看错,range 比 chomp 多花大约 53 纳秒。在某些情况下这可能是一个很大的拖累,但牢记绝对速度(而不仅仅是相对速度)可能会告诉您是否应该检查您的代码库并将所有范围更改为 chomps(如果适用)。可能不会。
  • 效果很好。您可以使用chomp!() 就地操作字符串。
【解决方案3】:

Ruby 2.5+

从 Ruby 2.5 开始,您可以使用 delete_suffixdelete_suffix! 以快速且可读的方式实现此目的。

方法的文档是here

如果你知道后缀是什么,这是惯用的(我认为,比这里的其他答案更具可读性):

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

它甚至比最佳答案快得多(使用 bang 方法几乎 40%)。以下是同一基准测试的结果:

                     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)

我希望这很有用 - 请注意,该方法目前不接受正则表达式,因此如果您不知道后缀,它暂时不可行。但是,由于接受的答案(更新:在撰写本文时)表明相同,我认为这可能对某些人有用。

【讨论】:

  • @JPSilvashy 失去复选标记我从未如此高兴过。这是一个很好的答案。
  • 这是一个很棒且快速的功能,但这不是正确的答案,因为它不能回答恰好是What is the preferred way of removing the last n characters from a string?的问题
  • 感谢@Sam 的反馈 - 这个问题的答案已经有将近九年了,与这个问题相同,在撰写本文时有 261 个赞成票。 JP 接受了这一点,最近改用了这个,所以我想说它回答了 他们的 问题 :) 我想我会把它作为一个现代的替代品,并希望它能帮助到这里的人。事实上,我已经在问题中涵盖了所有这些 - 我希望这个方法很快接受一个正则表达式,尽管在这个下面有一个完美的替代方案。
【解决方案4】:
str = str[0...-n]

【讨论】:

  • 请注意,这只适用于 Ruby 1.9。在 Ruby 1.8 中,这将删除最后的 bytes,而不是最后的 characters
  • 这比选择的答案要好,因为 3 个点 (...) 更容易记住,因为 -n 表示从字符串末尾取出 n 个字符。
  • 还有 "abcd"[0..-2] #=> "abc" 而 "abcd"[0...-2] #=> "ab"。在我看来,3 点范围选项会产生更不言自明的代码。
【解决方案5】:

我建议chop。我认为它已在其中一个 cmets 中提到,但没有链接或解释,所以这就是我认为它更好的原因:

它只是从字符串中删除最后一个字符,您不必为此指定任何值。

如果您需要删除多个字符,那么chomp 是您的最佳选择。这就是ruby docs 不得不说的chop

返回一个删除了最后一个字符的新字符串。如果字符串 以 \r\n 结尾,两个字符都被删除。将印章应用于空 string 返回一个空字符串。 String#chomp 通常更安全 替代方案,因为如果它不以 a 结尾,它会使字符串保持不变 记录分隔符。

虽然这主要用于删除分隔符,例如 \r\n,但我已经使用它来删除简单字符串中的最后一个字符,例如 s 以使单词成为单数。

【讨论】:

  • 那不只是删除最后一个字符吗?问题是关于复数中的“字符”
  • 是的,你是对的,但是 chomp('chars') 会删除最后一个 'chars'。我不清楚 OP 是想要特定字符还是只需要 N 个字符。
  • 是的,这就是答案,只有当您只想删除一个字符时(不过我就是这种情况)。
【解决方案6】:
name = "my text"
x.times do name.chop! end

在控制台中:

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

【讨论】:

  • 这样有效吗?似乎值得与其他答案进行基准比较:)
【解决方案7】:

删除最后一个 n 字符与保留第一个 length - n 字符相同。

主动支持包括 String#firstString#last 方法,它们提供了一种方便的方式来保留或删除第一个/最后一个 n 字符:

require 'active_support/core_ext/string/access'

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

【讨论】:

  • Rails 6.0 在"foobarbaz".first(-3) 上有一个贬损警告“使用负整数限制调用 String#first 将在 Rails 6.1 中引发 ArgumentError。”
【解决方案8】:

如果你正在使用 Rails,请尝试:

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

[编辑]

获取没有最后 2 个字符的字符串:

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

注意:最后一个字符串 char 在 n-1 处。因此,要删除最后 2 个,我们使用 n-3。

【讨论】:

  • 这不会删除最后两个字母。它返回它们。
  • 你不需要先测量字符串,ruby 原生使用字符串末尾的负索引
【解决方案9】:

【讨论】:

  • 请注意,这只适用于 Ruby 1.9。在 Ruby 1.8 中,这将删除最后的 bytes,而不是最后的 characters
【解决方案10】:

你总是可以使用类似的东西

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

其中X 是要删除的字符数。

或者分配/使用结果:

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

其中X 是要删除的加一字符数。

【讨论】:

    【解决方案11】:

    如果您可以创建类方法并希望删除字符,请尝试以下操作:

    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'
    

    【讨论】:

      【解决方案12】:

      使用正则表达式:

      str = 'string'
      n = 2  #to remove last n characters
      
      str[/\A.{#{str.size-n}}/] #=> "stri"
      

      【讨论】:

        【解决方案13】:
        x = "my_test"
        last_char = x.split('').last
        

        【讨论】:

        • 问题是关于从字符串中删除最后 N 个字符,而不是查找最后一个字符
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2011-05-10
        • 2018-12-03
        • 2014-11-08
        • 2015-02-23
        • 1970-01-01
        • 2017-08-19
        相关资源
        最近更新 更多