我有包含文件的目录,我想构建目录名称(作为键)和文件名称(作为值)的哈希。示例:
/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
但是它没有按预期方式工作,我不确定如何获取父目录名称。
答案 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::dirname和File::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=。