Feature #12698
closedMethod to delete a substring by regex match
Description
There is frequent need to delete a substring from a string. There already are methods String#delete
and String#delete!
, but their feature is a little bit different from the use cases that I am mentioning here.
I request methods that take a string or a regexp as an argument, and delete the matches from the receiver string. I am not sure of the method name, and I will use the term remove
here. It can be named in some other better way. I request all combinations of global vs. local, and non-destructive vs. destructive. The expected feature is something like the following. First, the non-destructive ones:
"abcabc".remove("c") # => "ababc"
"abcabc".remove(/\zc/) # => "abcab"
"abcabc".gremove("c") # => "abab"
"abcabc".gremove(/c/) # => "abab"
Then, the destructive ones:
s = "abcabc"
s.remove!("c") # => "ababc"
s # => "ababc"
s = "abcabc"
s.gremove!("d") # => nil
s # => "abcabc"
Using this, cases like https://bugs.ruby-lang.org/issues/12694 would be just special cases. They can be handled like this:
"abcdef".remove(/\Aabc/) # => "def"
Updated by sawa (Tsuyoshi Sawada) about 8 years ago
Perhaps my examples were not clear enough. My point is that, unlike String#delete
, the given string argument should not be interpreted as character classes, but rather as a substring. So, the following should also hold:
"abc".remove("cba") # => "abc"
"abc".remove("abc") # => ""
Updated by znz (Kazuhiro NISHIYAMA) about 8 years ago
Active Support already has String#remove
.
$ irb -r irb/completion --simple-prompt
>> require 'active_support/all'
=> true
>> "abcabc".remove("c")
=> "abab"
>> "abcabc".remove(/\zc/)
=> "abcabc"
>> "abcabc".remove(/c\z/)
=> "abcab"
>> "abcabc".remove(/\Aabc/)
=> "abc"
Updated by shevegen (Robert A. Heiler) about 8 years ago
I assume that this makes sense; my only concern is that ruby people may
be confused as to what to use. We have lots of ways :)
.gsub
.sub
.delete
.tr
[] =
Actually, I think my biggest complaint is that .delete() would sound
so similar to .remove() - .delete(/regex_here/) might be nice too.
But anyway, to conclude, I concur with the threadstarter in principle,
I think that ruby should know what to do when either a string is
given as argument or a regex so I am in principle in favour of the
suggestion.
Updated by matz (Yukihiro Matsumoto) almost 8 years ago
- Status changed from Open to Feedback
I don't think it's worth adding which is easily done by sub/gsub
.
Matz.
Updated by uchagani (Umair Chagani) over 7 years ago
Yukihiro Matsumoto wrote:
I don't think it's worth adding which is easily done by
sub/gsub
.Matz.
I think the problem goes beyond than that. String#delete takes a string as a parameter and natural thought progression would indicate that this acts as a substring delete. If String#delete took an array then its current behavior would make more sense.
Updated by svoop (Sven Schwyn) almost 6 years ago
matz (Yukihiro Matsumoto) wrote:
I don't think it's worth adding which is easily done by
sub/gsub
.
Easily done, yes, but Ruby being a very expressive language, the following two are not equally readable:
"foo test bar".gsub(/ test/, '')
"foo test bar".delete(/ test/)
Personally, I've never used String#delete
in almost 10 years of Ruby coding. It will be much more useful a method (and still downwards compatible) if it shifts from String#delete([other_str]+)
to String#delete([pattern|other_str]+)
.
Updated by duerst (Martin Dürst) almost 6 years ago
- Related to Feature #13890: Allow a regexp as an argument to 'count', to count more interesting things than single characters added
Updated by duerst (Martin Dürst) almost 6 years ago
matz (Yukihiro Matsumoto) wrote:
I don't think it's worth adding which is easily done by
sub/gsub
.
If put this way, it's easy to agree. But looking at it starting from String#delete
, it feels annoying that String#delete
doesn't accept a regular expression. If the above argument were taken to its full conclusion, it would mean that we could depreciate String#delete
, because str.delete chars
can be easily rewritten as str.gsub /[chars]/, ''
.
String#count
is a quite similar case, and even stronger, because in that case, it's not easy to replace it by sub/gsub
. See feature #13890.
The only other method on String
that has a list of characters as an argument is String#tr
. For that, I don't see how to add a regular expression as a parameter.
Updated by knu (Akinori MUSHA) almost 6 years ago
What about making the replacement of sub/gsub optional? (str.gsub(/re/, repl='')
)
sub
here might be considered as short for "subtract". 😆
Updated by svoop (Sven Schwyn) over 5 years ago
The suggestion by @knu (Akinori MUSHA) is pretty cool if you think about it: Since both sub
and gsub
exist, the uncertainty whether only one or all occurrences are deleted is gone. Also, with this in place, delete
could be deprecated IMO (and removed on Ruby 3 which will most likely break existing code in other places as well).
Updated by sawa (Tsuyoshi Sawada) almost 2 years ago
I now agree with https://bugs.ruby-lang.org/issues/12698#note-9. This issue can be considered to be along that line.