Project

General

Profile

Feature #12698

Method to delete a substring by regex match

Added by sawa (Tsuyoshi Sawada) over 2 years ago. Updated 3 months ago.

Status:
Feedback
Priority:
Normal
Assignee:
-
Target version:
-
[ruby-core:<unknown>]

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"

Related issues

Related to Ruby trunk - Feature #13890: Allow a regexp as an argument to 'count', to count more interesting things than single charactersOpenActions

History

Updated by sawa (Tsuyoshi Sawada) over 2 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) over 2 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) over 2 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) about 2 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) almost 2 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) 3 months 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]+).

#7

Updated by duerst (Martin Dürst) 3 months 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) 3 months 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) 3 months ago

What about making the replacement of sub/gsub optional? (str.gsub(/re/, repl=''))
sub here might be considered as short for "subtract". 😆

Also available in: Atom PDF