views:

123

answers:

4

The point here is to browse the array docfiles and return two arrays (temporary_file_paths and temporary_file_names).

I decided to return a Hash, but I feel I could get rid of the 2 temporary arrays but I'm not sure how...

   def self.foobar docfiles
        temporary_information = Hash.new
        temporary_file_paths = []
        temporary_file_names = [] 
        docfiles.each do |docfile|
          if File.exist? docfile.path
            temporary_file_paths << "new_path"
            temporary_file_names << "something_else"
          end
        end
        temporary_information[:file_paths] = temporary_file_paths
        temporary_information[:file_names] = temporary_file_names
        return temporary_information
    end
+6  A: 

Yes, just use them instead of your temporary hashes:

def self.foobar(docfiles)
    temporary_information = { :file_paths => [], :file_names => [] }
    docfiles.each do |docfile|
      if File.exist? docfile.path
        temporary_information[:file_paths] << new_path
        temporary_information[:file_names] << something_else
      end
    end
    return temporary_information
end
Doug Neiner
nice. I get an error on line 2 thought: "odd number list for Hash"
marcgg
@marcgg - Did you copy/paste? Line 2 compiles just fine for me...
Topher Fangio
weird... it works now. I must have been doing something wrong! Well if nothing better comes along this gets all my acceptance
marcgg
+1  A: 

It sounds like you might be going about the solution in an awkward way, but here is a simplified version of yours.

def self.foobar docfiles
     temporary_information = Hash.new
     temporary_information[:file_paths] = []
     temporary_information[:file_names] = []

     docfiles.each do |docfile|
       if File.exist? docfile.path
         temporary_information[:file_paths] << new_path
         temporary_information[:file_names] << something_else
       end
     end

     return temporary_information
 end

Also, as suggested by Alex, you can use inject. Below is a working example to show you a shortened version that I wrote before I saw Alex's post :-)

['test', 'test2', 'test3'].inject({}) { |result,element| { :file_paths => result[:file_paths].to_s + element, :file_names => result[:file_names].to_s + element } }
Topher Fangio
"It sounds like you might be going about the solution in an awkward way," => what do you mean?
marcgg
I used to do my file stuff just like this and then the light shone through when I found `File.glob`. Just seems like there might be a method already built-in to Ruby that does something similar to what you want :-)
Topher Fangio
I doubt it. Here I simplified it, but there's a lot more logic in this loop than what I pasted :)
marcgg
But this glob thing solved another of my problems!
marcgg
Glad it helped in some small way :-)
Topher Fangio
+2  A: 

You can avoid using the temporary arrays like so:

def self.foobar docfiles
  temporary_information = {:file_paths => [], :file_names => []}
  docfiles.each do |docfile|
    if File.exist? docfile.path
      temporary_information[:file_paths] << new_path
      temporary_information[:file_names] << something_else
    end
  end
  return temporary_information
end

You can also take this a step further and use inject:

def self.foobar docfiles
  docfiles.inject({:file_paths => [], :file_names => []}) do |temp_info,docfile|
    if File.exist? docfile.path
      temp_info[:file_paths] << new_path
      temp_info[:file_names] << something_else
      temp_info
    end
  end
end

This might be slightly cleaner, or not. I like inject but as I don't think there's any real difference in speed or efficiency this is probably just a matter of preference.

Alex Reisner
+1 - I like inject as well. Very clean and efficient, but a little bit hard to grasp for new rubyists :-)
Topher Fangio
The inject looks very interesting, +1 to that
marcgg
+7  A: 

There are tons of solutions here.

Returning a double value.

def self.foobar(docfiles)
   temporary_file_paths = []
   temporary_file_names = [] 
   docfiles.each do |docfile|
     if File.exist? docfile.path
       temporary_file_paths << new_path
       temporary_file_names << something_else
     end
   end
   [temporary_file_paths, temporary_file_names]
end

paths, names = Class.foo(...)

Using collect.

def self.foobar(docfiles)
  docfiles.map do |docfile|
    File.exist?(docfile.path) ? [new_path, something_else] : nil
  end.compact
end

paths, names = Class.foo(...)

Using inject (if you want a hash)

def self.foobar(docfiles)
  docfiles.inject({ :file_paths => [], :file_names => []}) do |all, docfile|
    if File.exist?(docfile.path)
      all[:file_paths] << new_path
      all[:file_names] << something_else
    end
    all
  end
end

All the solutions above don't change the main method logic. I don't like very much using arrays/hashes instead of objects so I usually end up converting hashes in objects when the execution requires multiple elaborations.

TemporaryFile = Struct.new(:path, :something_else)

def self.foobar docfiles
   docfiles.map do |docfile|
     if File.exist?(docfile.path)
       TemporaryFile.new(new_path, something_else)
     end
   end.compact
end

Also, I don't know the meaning of something else but if it's something you can get from the new_path, then you can use lazy execution.

TemporaryFile = Struct.new(:path) do
  def something_else
    # ...
  end
end

def self.foobar docfiles
   docfiles.map do |docfile|
     TemporaryFile.new(new_path) if File.exist?(docfile.path)
   end.compact
end
Simone Carletti
Why don't you like using hashes instead of object? In this situation don't you think it'd be overkill to do what you described in the second part of your answer?
marcgg
and I'd upvote you again for the double value return, I didn't know how to do that! That's pretty cool even thought people might get confused reading the code, I don't know...
marcgg
Using Hashes or not really depends on the real environment. If you need to make multiple elaborations on a single value like extract paths, compute "something else", then Objects are more flexible. I just wanted to provide a comprehensive set of solutions.
Simone Carletti
this makes sense.
marcgg