views:

218

answers:

1

I have negligible Ruby syntax knowledge and was hoping someone would be kind enough to translate the function below into pseudo code and possibly provide an example of how it would be called?

def in_list(num, list) 
   list = [*list] 
   list.each {|a,b| return (b)? num.sub(a,b) : a if num =~ a} 
   nil 
end
+10  A: 

Wow. That's some ugly ruby.

So num here is actually a String (the tip offs being the use of the #sub and #=~ methods.

list is an Array of

  • Regexp objects and/or
  • pairs of Regexp and replacement String objects.

If none of the given Regexps match the string, the method returns nil.

If an unpaired Regexp matches the string, the method returns that Regexp.

If a paired Regexp matches the string, the method substitutes the part of the string that the Regexp matches with the paired replacement text, and returns the modified String.

Once a Regexp matches the string, the method returns - no later Regexps are considered.

In no cases is the original String modified.

It's really a franken-method, IMHO, since it's trying to do very different things.

An example call:

 in_list("abe lincoln", [ [/linc/, 'zelda'] ]) #=> "abe zeldaoln"
 in_list("abe lincoln", [ [/linc/] ]) #=> /linc/
 in_list("abe lincoln", [ [/link/] ]) #=> nil

Really, with that multitude of return types, it seems like more of a pain in the ass than it's worth.

In pseudo-code

  DEF IN-LIST( text, regexps )
    FOREACH regexp IN regexps
      IF HAS-MATCH( text, regexp )
        IF HAS-REPLACEMENT-TEXT( regexp )
          RETURN REPLACE-MATCHED-PORTION( text, regexp, GET-REPLACEMENT-TEXT(regexp) )
        ELSE
          RETURN regexp
        ENDIF
      ENDIF
    ENDFOREACH
    RETURN NOTHING-FOUND
  ENDDEF

But like I said, this is some ugly-ass ruby. I'd avoid using it. It's a codesmell that tells me there's a whole lot wrong with this code.

If I had an array of Regexps, and wanted to find the first one that matched some text, I'd do:

# general case
regexps.find { |re| text =~ re }
# example
[ /earn/, /more/, /sessions/, /by/, /sleaving/ ].find { |re| "A baby?" =~ re } # would return /by/

If I had an collection of Regexp, replacement text pairs, and I wanted to replace the first match in some text, I'd do this

# general case
text_dupe = text.dup
pairs.find { |re,replace| text_dupe.sub!( re, replace ) }
# example
text_dupe = "One two three four".dup
[ [/ape/, 'frog'], [/our/, 'my'] ].find { |re,replace| text_dupe.sub!( re, replace } } # would return "One two three fmy"

I'd rather use a Hash for the last actually, but since that loses the order the original list came in (and who am I to say that's not important, not knowing how it's used), I didn't.

rampion
Was halfway through writing an answer when you posted yours. I'd come to the same conclusions re: regexp matching, and agree it is ugly as anything.
tomafro