How to define a Ruby method that accepts an array or string?

I defined a method that takes an array of (strings) like

def list(projects) puts projects.join(', ') end list(['a', 'b']) 

However, as a short hand to call it using an array that consists of only one String element, I would like the same function to also take one simple string, for example

  list('a') 

What will Ruby be for handling this method?

+7
string arrays ruby
source share
5 answers

Why not something like this:

 def list(*projects) projects.join(', ') end 

Then you can call it with as many arguments as you like

 list('a') #=> "a" list('a','b') #=> "a, b" arr = %w(abcdefg) list(*arr) #=> "a, b, c, d, e, f, g" list(arr,'h','i') #=> "a, b, c, d, e, f, g, h, i" 

Splat (*) automatically converts all arguments to an array, this will allow you to pass an array and / or string without any problems. This will work great with other objects.

 list(1,2,'three',arr,{"test" => "hash"}) #=> "1, 2, three, a, b, c, d, e, f, g, {\"test\"=>\"hash\"}" 

Thanks @Stefan and @WandMaker for pointing Array#join can handle nested arrays

+5
source share

You can check the input type, for example:

 >> a = ['foo', 'bar'] => ['foo', 'bar'] >> a.is_a? Array => true 

can you also check string using is_a?

As a result, you will receive a link:

 def list(projects) if projects.is_a? Array puts projects.join(', ') else puts projects end end list('a') # a list(['a', 'b']) # a, b 

Do you have many ways to do this in Ruby, respond_to? and kind_of? also work

+4
source share

One way - you can enter an input type:

 def list(projects) if projects.is_a?(String) projects = [projects] end puts projects.join(', ') end 

Or you can use Array() to automatically convert a string to an array, or leave only an existing array:

 def list(projects) Array(projects).join(', ') end 
+1
source share

I would request the provided value if it responds to join :

 def list(projects) projects.respond_to?(:join) ? projects.join(', ') : projects end 
+1
source share
 def list(projects) puts ([*projects]).join(', ') end list(['a', 'b']) a, b list('a') a 

Caution: do not use this.

I posted this solution only to demonstrate the trick that it uses. @sawa, in his now deleted answer, is right: method users should not be allowed to pass an array as an argument. Instead, they should be limited to the transfer of individual elements. If a:

 arr = [1,2,3] 

The method is called by one of the following:

 list 1 list 1,2 list 1,2,3 list *arr 

but not:

 list arr 

This simplifies the method and makes its application more consistent. Ask yourself: why allow arr instead of *arr ? To save one character?

The method that does this answers @engineersmnky with the removal of .flatten .

+1
source share

All Articles