我有带有文件的目录,我想构建目录名称作为键和文件名作为值的目录。示例:
/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
但是它没有预期的工作,我不确定如何获取父目录名称。
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(aka merge!
((,file :: dirname and 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({})>
第一个值是由枚举器生成并传递到块的,并且通过数组分解过程分配了块变量:
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"=>{}}
请参阅枚举#下一篇。下一个值是由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]={}}
。请参阅哈希#default_proc =。
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:
对File.glob
的关键字参数(或Pathname.glob
,就此而言(,这简化了我们不需要删除app
的内容;另外,出于OP的问题的目的,只需要一个目录级别,因此*
代替**
。