Search code examples
rubyarrayson-the-fly

Create array without declaring it first - Ruby


I'm sorry if this question is a dumb one, but I must ask. In PHP, we can create a array without declaring it first, althought it isn't considered good pratice. Exercising my newly-knowledge of Ruby, I was writing a code to list the files inside a directory and sort them by their extensions. To do this, I started a loop to put them in differents arrays based on their extensions. Like this:

files_by_ext = {} #edited - my bad, it was supposed to be {}
files_by_ext['css'] = ['file.css','file2.css','file3.css']
files_by_ext['html'] = ['file.html','file2.html','file3.html']

Then I would sort using the keys 'css' and 'html'. But in the process to create the array of "X" files, I needed to verify if the key "X" existed. I couldn't simply push the file(eg. 'file.X').

There is a way to create methods to alter this behavior, so that I can create a array pushing a item without declaring it first?

files.each do |f|
 extension = /\.(.+)$/.match(f)[1].to_s
 files_by_ext[extension] << f
end

And not(that's what I'm doing):

files.each do |f|
 extension = /\.(.+)$/.match(f)[1].to_s
 if !files_by_ext.key?(extension)
  files_by_ext[extension] = [f]
 else
  files_by_ext[extension] << f
 end
end

I'm sorry, I think I wrote too much. :P Thank you for reading.


Solution

  • In order to set a default value of Array.new, you must pass Hash.new a block and assign a new array into the Hash each time a new key is used. This is the only correct way to do this:

    files_by_ext = Hash.new { |hsh, key| hsh[key] = Array.new }
    

    You can then use the keys in that hash as if every key already has an array in it.

    files_by_ext['.com'] << 'command.com'
    

    An alternative approach which is very commonly used is to do the following:

    files_by_ext = Hash.new
    # ... later ...
    files_by_ext['.com'] ||= Array.new
    files_by_ext['.com'] << 'command.com'