开发者

Ruby: Split string at character, counting from the right side

开发者 https://www.devze.com 2022-12-13 01:04 出处:网络
Short version -- How do I do Python rsplit() in ruby? Longer version -- If I want to split a string into two parts (name, suffix) at the first \'.\' character, this does the job nicely:

Short version -- How do I do Python rsplit() in ruby?

Longer version -- If I want to split a string into two parts (name, suffix) at the first '.' character, this does the job nicely:

name, suffix = name.split('.', 2)

But if I want to split at the last (rightmost) '.' character, I haven't been able to come up with anything more elegant than this:

idx = name.rindex('.')
name, suffix = name[0..idx-1], name[idx+1..-1] if idx

Note that the original name string may not have a dot at all, in which case name should be untouched and suffix should be nil; i开发者_开发技巧t may also have more than one dot, in which case only the bit after the final one should be the suffix.


String#rpartition does just that:

name, match, suffix = name.rpartition('.')

It was introduced in Ruby 1.8.7, so if running an earlier version you can use require 'backports/1.8.7/string/rpartition' for that to work.


Put on the thinking cap for a while and came up with this regexp:

"what.to.do.now".split(/\.([^.]*)$/)
=> ["what.to.do", "now"]

Or in human terms "split at dot, not followed by another dot, at end of string". Works nicely also with dotless strings and sequences of dots:

"whattodonow".split(/\.([^.]*)$/)
=> ["whattodonow"]
"what.to.do...now".split(/\.([^.]*)$/)
=> ["what.to.do..", "now"]


Here's what I'd actually do:

/(.*)\.(.*)/.match("what.to.do")[1..2]
=> ["what.to", "do"]

or perhaps more conventionally,

s = "what.to.do"

s.match(/(.*)\.(.*)/)[1..2]
=> ["what.to", "do"]


If you want the literal version of rsplit, you can do this (this is partly a joke, but actually works well):

"what.to.do".reverse.split('.', 2).map(&:reverse).reverse
=> ["what.to", "do"]


if this="what.to.do" you can do this:

this.split(%r{(.+)\.})

and you'll get back

["", "what.to", "do"]


You can also add rsplit to the String class by adding this at the top of your file.

class String
  def rsplit(pattern=nil, limit=nil)
    array = self.split(pattern)
    left = array[0...-limit].join(pattern)
    right_spits = array[-limit..]
    return [left] + right_spits
  end
end

It doesn't quite work like split. e.g.

$ pry
[1] pry(main)> s = "test.test.test"
=> "test.test.test"
[2] pry(main)> s.split('.', 1)
=> ["test.test.test"]
[3] pry(main)> s.split('.', 2)
=> ["test", "test.test"]
[4] pry(main)> s.split('.', 3)
=> ["test", "test", "test"]

vs.

[6] pry(main)> s
=> "test.test.test"
[7] pry(main)> s.rsplit('.', 1)
=> ["test.test", "test"]
[8] pry(main)> s.rsplit('.', 2)
=> ["test", "test", "test"]

But I can't quite work out how to short split it.

0

精彩评论

暂无评论...
验证码 换一张
取 消