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
精彩评论