简体   繁体   English

如何改善此ruby代码和对哈希的使用?

[英]How can I improve this ruby code and my use of Hashes?

The point here is to browse the array docfiles and return two arrays ( temporary_file_paths and temporary_file_names ). 这里的重点是浏览数组docfiles并返回两个数组( temporary_file_paths docfilestemporary_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

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. 另外,我不知道的意思something别人,但如果它的东西,你可以从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

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

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 : 您还可以更进一步,并使用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. 我喜欢inject但由于我不认为速度或效率有任何实际差异,所以这可能只是偏好问题。

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 . 另外,根据Alex的建议,您可以使用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 } }

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM