在红宝石中嵌套太多了?

时间:2011-08-23 13:43:14

标签: ruby nested

当然必须有更好的方法:

File.open('Data/Networks/to_process.txt', 'w') do |out|
  Dir['Data/Networks/*'].each do |f|
    if File.directory?(f)
      File.open("#{f}/list.txt").each do |line|
        out.puts File.basename(f) + "/" + line.split(" ")[0]
      end
    end
  end
end 

干杯!

4 个答案:

答案 0 :(得分:8)

您可以使用Guard Clause模式删除1级嵌套:

File.open('Data/Networks/to_process.txt', 'w') do |out|
  Dir['Data/Networks/*'].each do |f|
    next unless File.directory?(f)
    File.open("#{f}/list.txt").each do |line|
      out.puts File.basename(f) + "/" + line.split(" ")[0]
    end
  end
end

有关此方法的信息,请参阅Jeff Atwood's article

答案 1 :(得分:6)

恕我直言,您的代码没有任何问题,但您可以在一个语句中执行目录通配和来自if的检查,从而节省了一级嵌套:

Dir.glob('Data/Networks/*').select { |fn| File.directory?(fn) }.each do |f|
  ...
end

答案 2 :(得分:3)

由于您要在每个目录中查找特定文件,只需让Dir#[]找到它们,完全不需要检查目录。此外,IO#puts将接受一个数组,将每个元素放在一个新行上。这将摆脱另一层次的嵌套。

File.open('Data/Networks/to_process.txt', 'w') do |out|
  Dir['Data/Networks/*/list.txt'] do |file|
    dir = File.basename(File.dirname(file))
    out.puts File.readlines(file).map { |l| "#{dir}/#{l.split.first}" }
  end
end

答案 3 :(得分:1)

通过将输入与输出分开来减少嵌套:

directories = Dir['Data/Networks/*'].find_all{|f| File.directory?(f)}
output_lines = directories.flat_map do |f|
  output_lines_for_directory = File.open("#{f}/list.txt").map do |line|
    File.basename(f) + "/" + line.split(" ")[0]
  end
end
File.open('Data/Networks/to_process.txt', 'w') do |out|
  out.puts output_lines.join("\n")
end