How can you make a ruby function accept either an individual item or collection of items and do the same thing?
I'm trying to write a function that would apply the function to just one item if it's not a collection, or else apply that function to each of the collections elements. For example:
replace spaces with undersc开发者_JS百科ores
foo 'a bear' => 'a_bear'
foo ['a bear', 'a bee'] => ['a_bear', 'a_bee']
Is this possible?
It depends on how you define "collection". The most natural option would probably be either "any Enumerable" or even "anything with an each method". However this leads to a problem because Strings are Enumerable, too - in ruby 1.8, at least.
If you only need it to work with arrays, it's easy:
def foo(x)
  if x.is_a? Array
    x.map {|item| foo(item)}
  else
    # Do something with x
  end
end
Personally I would use variable args:
def foo(*args)
  args.each { |arg| puts arg }
end
foo("bar")                    # bar
foo("bar", "foobar")          # bar \n foobar
foo(*%w(bar foobar))          # bar \n foobar
a = ["bar", "foobar"]
foo(*a)                       # bar \n foobar
foo("baz", *a)                # baz \n bar \n foobar
a = "bar"
foo(*a)                       # bar
If you don't know whether or not your argument is a string or an array then just prepend it with a *.
I find this gives the maximum flexibility when dealing with arrays which might instead be a single value as I can enter them as just arguments if I am initializing the array or safely pass in the variable if I know it will either be an array or a single argument. It will choke on hashes though.
You may be interested in the splat operator
def foo(x)
  [*x].map {|item| item.gsub(" ", "_")}
end
Unfortunately, this'd return foo("a bear") as ["a_bear"], rather than "a_bear" without the array.
Not sure if I'm misreading the question or not. The below will make it so a function will treat either a single element or an array of elements the same way. Just array-ifies the argument if it's not already an array, and undoes that at the end if necessary.
def foo(x)
  x = [x] unless x.is_a? Array
  # do array stuff to x
  return result.size > 1 ? result : result.first
end
 
         加载中,请稍侯......
 加载中,请稍侯......
      
精彩评论