From: William James Date: 2007-10-03T00:15:09+09:00 Subject: Re: help in my own gsub design.. On Oct 2, 8:24 am, Josselin wrote: > On 2007-10-02 14:46:48 +0200, William James said: > > > On Oct 2, 6:35 am, Josselin wrote: > >> I don't use it very often, rather copying from example, but it's so > >> useful that I should learn how to write it > >> I'd appreciate any guru tip on how to proceed once the problem is on > >> the paper : > > >> example : > > >> INPUT STRINGS > > >> 1- input can contains spaces (should be eliminated) > > >> 2- good patterns : > > >> 2a- an Integer like 99 (no limit) > >> a > >= < <= <> != followed by an Integer like >99 > > >>> =99 <99 <=99 <>99 !=99 > > >> 2b- a String like: abcd abc99 99abc a99bc > > >> 2c- a % sign followed by a String > >> like %abcd %abc99 %99abc %a99bc %abcd > > >> 2d- a String followed by a % sign > >> like abcd% abc99% 99abc% a99bc% > > >> 2e- a String leading containing or ending with, one or many * sign(s) > >> like a*bcd a**bc99 99*a*bc *a99bc a99bc* *a99bc* *a9**9b*c* > > >> 3-any other pattern will be considered as wrong > > >> OUTPUTS > > >> 2a -> an array [characters, Integer] like [ "<>", 99] > >> 2b, 2c, 2d,2e -> an array [ nil, String] like [nil, abcd] or [nil, > >> %abcd] or [nil, a99bc%] or [nil, *a9**9b*c] > > >> I am interesting in understanding the design process... : how should I > >> start when designing such gsub routine ? > >> should I state it differently on paper first ? well, any tip that can > >> help me to build the next ones.... > > >> thanks for your support > > >> joss > > > def foo s > > case s > > when /^(>|>=|<|<=|<>|!=)?(\d+)$/ > > [ $1 || "", $2.to_i ] > > when /^(%)?[a-z\d]+(%)?$/ > > return nil if 1 != $~.captures.compact.size > > [ nil, $& ] > > when /^(?=.*\*)[*a-z\d]+$/ > > [ nil, $& ] > > end > > end > > > p foo( "88" ) > > p foo( "<>88" ) > > p foo( "%33" ) > > p foo( "33%" ) > > p foo( "a*9" ) > > p foo( 'bat' ) > > thanks a lot , William, I can see how you built it.. I just have 2 > points to clarify if you don't mind > > 1- return nil if 1 != $~.captures.compact.size > I don't catch up I wrote the function so that it will return nil if the string doesn't match your patterns. The line above is equivalent to if 1 != $~.captures.compact.size return nil end The number of succesful captures (captured by /^(%)?[a-z\d]+(%)?$/ ) must be exactly 1; i.e., the string must begin or end with %, but not both. > > 2- (?=.*\*) (?=...) is a zero-width look-ahead; it looks ahead but it doesn't move ahead in the string. I put this here to make sure that the string contains at least one *. > > otherwise I commented it .. is my understanding correct ? > > def foo s > case s I forgot about spaces. If they can only be at the start or end of the string, use case s.strip > when /^(>|>=|<|<=|<>|!=)?(\d+)$/ > # start with > OR >= OR < OR <= OR <> OR != (0 or 1 time) then > digit(0-9) n times 1 or more times. > [ $1 || "", $2.to_i ] > # first element or nil , second element to integer If 1st capture is nil, use ""; else use 1st capture. > > when /^(%)?[a-z\d]+(%)?$/ > # start with % ( 0 or 1 time) then characters a-zA-Z 1 or n times then > end with % ( 0 or 1 time) > return nil if 1 != $~.captures.compact.size > # return nil if ..... > [ nil, $& ] > # first element nil, second element = parameter This is a good point. Instead of $& (what was matched by the reg.ex.) I should have used the parameter of the function, s. > > when /^(?=.*\*)[*a-z\d]+$/ > # start with *( 0 or n times)...... then characters *a-zA-Z 1 or n tiems > [ nil, $& ] > # first element nil, second element = parameter > end > end