Feature #3388
closedregexp support for start_with? and end_with?
Description
=begin
ruby-1.9.2-head > "aBcdeFghIj".start_with?(/abc/i)
=> false
In my implementation of start_with? it is easy enough to utilize #index, which works fine:
def start_with?(pattern)
index(pattern) == 0
end
But #end_with? is more difficult, and I had to use regular expressions.
def end_with?(suffix)
suffix = Regexp.escape(suffix) if String===suffix
/#{suffix}$/.match(self) ? true : false
end
However, we might get rid of the '? true : false' and return the MatchData, since that could be useful information.
=end
Files
Updated by naruse (Yui NARUSE) over 14 years ago
=begin
def end_with?(suffix)
if suffix.kind_of(String)
index(suffix) + suffix.length == self.length
else
m = suffix.match(self)
m ? m.post_match.empty? : false
end
end
=end
Updated by marcandre (Marc-Andre Lafortune) over 14 years ago
- Category set to core
=begin
I'm moving this to the feature's tracker, since I feel it would make a valid addition.
PS: Yui, that code won't work:
"Hello world. Bye".end_with? /e/ # => false
=end
Updated by marcandre (Marc-Andre Lafortune) over 14 years ago
- Category set to core
- Status changed from Rejected to Open
- Target version set to 2.0.0
=begin
=end
Updated by nobu (Nobuyoshi Nakada) over 14 years ago
=begin
def start_with?(pattern)
!!rindex(pattern, 0)
end
def end_with(pattern)
rindex(pattern) and (!$& || $~.end(0) == length) or false
end
=end
Updated by nobu (Nobuyoshi Nakada) over 14 years ago
=begin
Missed.
def end_with?
i = rindex(pattern) and ($& ? $~.end(0) : i + pattern.length) == length or false
end
or
def end_with?(pattern)
if String === pattern
!!index(pattern, -pattern.length)
else
rindex(pattern) and $~.end(0) == length or false
end
end
=end
Updated by nahi (Hiroshi Nakamura) almost 13 years ago
- Description updated (diff)
rindex(pattern) would fail to detect proper end_of_string index. It must be /{suffix}\Z/.
Updated by akr (Akira Tanaka) almost 13 years ago
I think we can cache regexp structure according to regexp source, options, encoding.
If regexp structure is cached, /\A#{pattern}/ and /#{pattern}\z/ is not slow for
second and successive dynamic regexp creation.
If it is not slow, we can use them to implement String#{start_with?,end_with?} for regexp.
Updated by mame (Yusuke Endoh) over 12 years ago
- Status changed from Open to Feedback
A patch is welcome.
--
Yusuke Endoh mame@tsg.ne.jp
Updated by Eregon (Benoit Daloze) over 12 years ago
A patch is welcome.
I'm willing to give this a shot, but I think #5536 should be merged first.
Updated by Eregon (Benoit Daloze) over 12 years ago
- File 0001-string.c-rb_str_start_with-rb_str_end_with-allow-Reg.patch 0001-string.c-rb_str_start_with-rb_str_end_with-allow-Reg.patch added
Here is an attempt adding \A or \z to the Regexp's source and creating a new Regexp with it.
An alternative would be to call #to_s on the Regexp and add the anchor, but it seems cleaner to preserve options as global options.
What do you think?
akr: How would you cache the regexp structure?
Updated by ko1 (Koichi Sasada) about 12 years ago
- Assignee set to naruse (Yui NARUSE)
Updated by Eregon (Benoit Daloze) about 12 years ago
I had a try implementing a global persistent cache for Regexps.
Is a global persistent cache OK? It seems bad for dynamically created regexps.
Maybe some kind of weak reference map?
akr: What kind of cache did you think to?
Updated by headius (Charles Nutter) about 12 years ago
JRuby currently does have a global cache for regexps. If you're interested, one of us can show you how it works.
Updated by Eregon (Benoit Daloze) about 12 years ago
headius (Charles Nutter) wrote:
JRuby currently does have a global cache for regexps. If you're interested, one of us can show you how it works.
Interesting. I see it's implemented using a SoftReference map.
I'm not aware of something similar in MRI.
If I read right, the only Regexp cache in MRI is a single last-used cache used in some String methods (match,scan,split,...).
It would be nice if we could differentiate static and dynamic regexps, but in any case I guess I could do a last-used cache as in re.c.
Updated by mame (Yusuke Endoh) about 12 years ago
- Target version changed from 2.0.0 to 2.6
Updated by mame (Yusuke Endoh) about 7 years ago
After that, String#start_with?
now accepts regexp (#13712). But end_with?
does not support regexp yet because we don't have a direct use case for end_with?
(and because of the difficulty of implementation).
Updated by mame (Yusuke Endoh) about 7 years ago
- Related to Feature #13712: String#start_with? with regexp added