3

I have a string, e.g.

string = 'foo-bar'

and I want a new string which doesn't contain the character at index 3 (the - in the example string), so the results would be "foobar". The former string must not be changed.

This is what I have so far:

new_string = string.dup
new_string.slice!(3)
new_string
#=> "foobar"

string
#=> "foo-bar"

or as a "one-liner":

new_string = string.dup.tap { |s| s.slice!(3) }
#=> "foobar"

But having to dup and maybe tap looks quite cumbersome. Is there a more concise way?

7
  • I don't know if such method exists already, but you can always create one, and hide the dup/tap there. Commented May 23, 2018 at 9:40
  • @SergioTulentsev I though that I might be overlooking an obvious solution. Commented May 23, 2018 at 9:42
  • It certainly feels that way, yes. Commented May 23, 2018 at 9:45
  • 1
    Coincidentally there is a recent feature request for dup accepting a tap-like block. Not sure if that's a good idea though. Commented May 23, 2018 at 9:50
  • FYI I've opened a feature request for what I think would be a viable solution to my problem: bugs.ruby-lang.org/issues/14783 Commented May 23, 2018 at 10:24

2 Answers 2

2

I'm not aware of such a method. You can write it yourself using slice though.

at = 3
string = "abc-def"
def delete_at(string, at)
  string.slice(0, at) + string.slice(at + 1, string.length)
end

x = delete_at(string, at) #> "abcdef"

You could also monkey patch it to String class (which I don't like though)

Sign up to request clarification or add additional context in comments.

4 Comments

Alternatively string[0...at] + string[at + 1..-1]
@Stefan yes, that would work as well. I think that [] is way to overloaded though. So I never use it. ruby-doc.org/core-2.5.1/String.html#method-i-5B-5D
String#[] and String#slice are aliases.
@Stefan overloaded in the sense that it is used for lots of things e.g. accessing elements if an Array/Hash and my brain does not parse String[] well :-)
1

Seems Kernel#sprintfcan solve this fairly simply:

str = "foo-bar"
sprintf("%3.3s%s",str,str[4..-1])
#=> "foobar"

Or simply

sprintf("%s%s",str[0..2],str[4..-1])
#=> "foobar"

Additionally Enumerable methods could help but seem a bit overkill e.g.

str.each_char.with_index.reduce("")  do |memo,(s,i)| 
  i == 3 ? memo : memo << s
end
#=> "foobar"

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.