如何改进这个ruby代码和我对Hashes的使用?

时间:2009-12-21 15:54:34

标签: ruby-on-rails ruby

这里的要点是浏览数组docfiles并返回两个数组(temporary_file_pathstemporary_file_names)。

我决定返回哈希,但我觉得我可以摆脱2个临时阵列,但我不确定如何......

   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

4 个答案:

答案 0 :(得分:7)

这里有很多解决方案。

返回双倍值。

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(...)

使用收藏。

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

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

使用注入(如果您想要哈希)

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

上述所有解决方案都不会更改主方法逻辑。 我不太喜欢使用数组/散列而不是对象,因此当执行需要多次详细说明时,我通常最终会在对象中转换哈希值。

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

另外,我不知道something else的含义,但是如果你可以从new_path得到它,那么你可以使用延迟执行。

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

答案 1 :(得分:6)

是的,只需使用它们而不是临时哈希:

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

答案 2 :(得分:2)

您可以避免像这样使用临时数组:

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

您还可以更进一步,使用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

这可能会稍微清洁一下。我喜欢inject,但由于我认为速度或效率没有任何实际差异,这可能仅仅是一个偏好问题。

答案 3 :(得分:1)

听起来你可能会以尴尬的方式解决这个问题,但这是你的简化版本。

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

另外,正如Alex建议的那样,您可以使用inject。下面是一个工作示例,向您展示我在看到Alex的帖子之前写的缩短版本: - )

['test', 'test2', 'test3'].inject({}) { |result,element| { :file_paths => result[:file_paths].to_s + element, :file_names => result[:file_names].to_s + element } }