2009-12-21 56 views
1

这里的要点是用于浏览数组docfiles和返回两个阵列(temporary_file_pathstemporary_file_names)。我该如何改进这个ruby代码和我对Hashes的使用?

我决定返回一个哈希,但我觉得我可以摆脱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 

回答

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的意思,但如果它的东西,你可以从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 
+0

为什么不喜欢使用散列而不是对象?在这种情况下,你认为在你的答案的第二部分做你所描述的内容会是多么的矫枉过正? – marcgg 2009-12-21 16:23:50

+0

,我会再次为您提供双倍的价值回报,我不知道该怎么做!这很酷,甚至认为人们可能会阅读代码时感到困惑,我不知道...... – marcgg 2009-12-21 16:25:01

+0

使用Hashes或不是真的取决于真实的环境。如果您需要对提取路径等单个值进行多个细化,请计算“其他”,然后对象更加灵活。我只是想提供一套全面的解决方案。 – 2009-12-21 16:37:28

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 
+0

不错。我在第二行得到一个错误思想:“奇数号码列表哈希 ” – marcgg 2009-12-21 16:01:02

+0

@marcgg - 你复制/粘贴?第2行编译对我来说很好... – 2009-12-21 16:03:10

+0

很奇怪...现在可以工作。我一定是做错了!那么,如果没有更好的事情发生,这将得到我所有的接受 – marcgg 2009-12-21 16:04:48

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 } } 
+0

“这听起来像你可能会以一种尴尬的方式解决方案,”=>你是什么意思? – marcgg 2009-12-21 16:03:12

+0

我曾经这样做我的文件的东西,然后当我发现'File.glob'时,光照。只是似乎可能有一种方法已经内置到Ruby,做了类似于你想要的东西:-) – 2009-12-21 16:39:14

+0

我对此表示怀疑。这里我简化了它,但是这个循环中的逻辑比我粘贴的要多:) – marcgg 2009-12-21 17:25:34

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,但由于我不认为在速度或效率方面有任何实质性差异,所以这可能只是一个偏好问题。

+1

+1 - 我喜欢注射。非常干净而高效,但是对于新的rubyist来说有点难以掌握:-) – 2009-12-21 16:12:05

+0

注入看起来非常有趣,+1对于 – marcgg 2009-12-21 16:25:35