如何在Ruby中建立目录名称(作为键)和文件名称(作为值)的哈希?

时间:2019-05-12 23:31:22

标签: ruby-on-rails ruby

我有包含文件的目录,我想构建目录名称(作为键)和文件名称(作为值)的哈希。示例:

/app/foo/create.json
/app/foo/update.json
/app/bar/create.json
/app/bar/update.json

输出:

{
  "foo" => {
    "create.json" => {},
    "update.json" => {}
  },
  "bar" => {
    "create.json" => {},
    "update.json" => {}
  }
}

目前我正在这样做:

OUTPUT ||= {}

Dir.glob('app', '**', '*.json')) do |file|
  OUTPUT[File.basename(file)] = File.read(file)
end

但是它没有按预期方式工作,我不确定如何获取父目录名称。

2 个答案:

答案 0 :(得分:1)

regexp的替代方法:

output =
    Dir.glob('*/*.json', base: 'app').
    group_by(&File::method(:dirname)).
    transform_values { |files|
      files.each_with_object({}) { |file, hash|
        hash[File.basename(file)] = File.read(file)
      }
    }

请注意base:的{​​{1}}关键字参数(或File.glob),它简化了事情,因为我们不需要删除Pathname.glob;同样,出于OP的问题,只需要一个目录级别,因此app而不是*

答案 1 :(得分:1)

Dir.glob('*/*.json', base: 'app').each_with_object(Hash.new {|g,k| g[k]={}}) do |fname,h|
  h[File.dirname(fname)].update(File.basename(fname)=>{})
end
  #=> {"foo"=>{"create.json"=>{}, "update.json"=>{}},
  #    "bar"=>{"update.json"=>{}, "create.json"=>{}}}

@Amadan解释了Dir#glob的用法,这与他的回答完全相同。我采用了Hash::new的版本,该版本在执行{|g,k| g[k]={}}且散列g[k]没有键g时调用一个块(此处为k)。 1。另请参见Hash#update(又名merge!),File::dirnameFile::basename

步骤如下。

a = Dir.glob('*/*.json', base: 'app')
  #=> ["foo/create.json", "foo/update.json", "bar/update.json", "bar/create.json"] 
enum = a.each_with_object(Hash.new {|g,k| g[k]={}})
  #=> #<Enumerator: ["foo/create.json", "foo/update.json", "bar/update.json",
  #                  "bar/create.json"]:each_with_object({})> 

第一个值由枚举器生成并传递给块,并且通过array decomposition的过程为块变量分配值:

fname, h = enum.next
  #=> ["foo/create.json", {}] 
fname
  #=> "foo/create.json" 
h #=> {} 
d = File.dirname(fname)
  #=> "foo" 
b = File.basename(fname)
  #=> "create.json" 
h[d].update(b=>{})
  #=> {"create.json"=>{}}

请参见Enumerator#next。下一个值由enum生成并传递给块,为块变量分配值,并执行块计算。 (请注意,正在构建的哈希h已在以下更新。)

fname, h = enum.next
  #=> ["foo/update.json", {"foo"=>{"create.json"=>{}}}] 
fname
  #=> "foo/update.json" 
h #=> {"foo"=>{"create.json"=>{}}} 
d = File.dirname(fname)
  #=> "foo" 
b = File.basename(fname)
  #=> "update.json" 
h[d].update(b=>{})
  #=> {"create.json"=>{}, "update.json"=>{}} 

再两倍。

fname, h = enum.next
  #=> ["bar/update.json", {"foo"=>{"create.json"=>{}, "update.json"=>{}}}] 
d = File.dirname(fname)
  #=> "bar" 
b = File.basename(fname)
  #=> "update.json" 
h[d].update(b=>{})
  #=> {"update.json"=>{}} 

fname, h = enum.next
  #=> ["bar/create.json",
  #    {"foo"=>{"create.json"=>{}, "update.json"=>{}}, "bar"=>{"update.json"=>{}}}] 
d = File.dirname(fname)
  #=> "bar" 
b = File.basename(fname)
  #=> "create.json" 
h[d].update(b=>{})
  #=> {"update.json"=>{}, "create.json"=>{}} 
h #=> {"foo"=>{"create.json"=>{}, "update.json"=>{}},
  #    "bar"=>{"update.json"=>{}, "create.json"=>{}}} 

1。这等效于按以下方式定义哈希:g = {}; g.default_proc = proc {|g,k| g[k]={}}。参见Hash#default_proc=