在Ruby中对多个目录项进行排序
如果我有以下文件,并且它们有以下路径(为简单起见进行了更改) 我如何对它们进行排序以得到这样的散列在Ruby中对多个目录项进行排序,ruby,Ruby,如果我有以下文件,并且它们有以下路径(为简单起见进行了更改) 我如何对它们进行排序以得到这样的散列 sort_directory(array) #=> { "dir1" => { "a" => [ "root_path/dir1/a/file.jpg", "root_path/dir1/a/file2.jpg" ], "b" => [ "root_path/dir1/b/file3.jpg" ]
sort_directory(array)
#=>
{
"dir1" => {
"a" => [
"root_path/dir1/a/file.jpg",
"root_path/dir1/a/file2.jpg"
],
"b" => [
"root_path/dir1/b/file3.jpg"
]
},
"dir2" => {
"c" => [
"root_path/dir2/c/file4.jpg"
]
}
}
使用、和/或某些正则表达式的一种方法
array.group_by{ |dir| dir.split('/')[1] }.map{ |k,v| {k => v.group_by{ |file| file[/\/([^\/]+)(?=\/[^\/]+\/?\Z)/, 1]} } }
下面是如何使用递归来获得所需的结果 如果
s=“root\u path/dir1/a/b/c/file.jpg”
,我们可以认为“root\u path”
位于“位置”0,“dir1”
位于位置1,依此类推。OP给出的示例需要对位置1和2处的值进行分组,我将编写positions=[1,2]
分组的位置数量或顺序没有限制。对于上面的字符串,我们可以编写,例如,positions=[2,4,1]
,因此第一个分组将位于位置2,第二个分组位于位置4,最后一个分组位于位置1(尽管我不知道这是否有意义)
代码
def hashify(arr, positions)
recurse(positions, arr.map { |s| s.split("/") })
end
def recurse(positions, parts)
return parts.map { |a| a.join('/') } if positions.empty?
pos, *positions = positions
h = parts.group_by { |a| a[pos] }.
each_with_object({}) { |(k,a),g| g[k]=recurse(positions, a) }
end
arr = ["root_path/dir1/a/file.jpg",
"root_path/dir1/a/file2.jpg",
"root_path/dir1/b/file3.jpg",
"root_path/dir2/c/file4.jpg"]
hashify(arr, [1, 2])
#=>{"dir1"=>{"a"=>["root_path/dir1/a/file.jpg", "root_path/dir1/a/file2.jpg"],
# "b"=>["root_path/dir1/b/file3.jpg"]},
# "dir2"=>{"c"=>["root_path/dir2/c/file4.jpg"]}}
示例
def hashify(arr, positions)
recurse(positions, arr.map { |s| s.split("/") })
end
def recurse(positions, parts)
return parts.map { |a| a.join('/') } if positions.empty?
pos, *positions = positions
h = parts.group_by { |a| a[pos] }.
each_with_object({}) { |(k,a),g| g[k]=recurse(positions, a) }
end
arr = ["root_path/dir1/a/file.jpg",
"root_path/dir1/a/file2.jpg",
"root_path/dir1/b/file3.jpg",
"root_path/dir2/c/file4.jpg"]
hashify(arr, [1, 2])
#=>{"dir1"=>{"a"=>["root_path/dir1/a/file.jpg", "root_path/dir1/a/file2.jpg"],
# "b"=>["root_path/dir1/b/file3.jpg"]},
# "dir2"=>{"c"=>["root_path/dir2/c/file4.jpg"]}}
解释
递归方法很难解释。在我看来,最好的方法是插入put
语句来显示计算顺序。每当该方法调用自身时,我也缩进了一些空格。下面是如何为此目的修改代码
INDENT = 4
def hashify(arr, positions)
recurse(positions, arr.map { |s| s.split("/") }, 0)
end
def recurse(positions, parts, lvl)
puts
"lvl=#{lvl}".pr(lvl)
"positions=#{ positions }".pr(lvl)
if positions.empty?
"parts=#{parts}".pr(lvl)
return parts.map { |a| a.join('/') }
end
pos, *positions = positions
"pos=#{pos}, positions=#{positions}".pr(lvl)
h = parts.group_by { |a| a[pos] }
"h=#{h}".pr(lvl)
g = h.each_with_object({}) { |(k,a),g| g[k]=recurse(positions, a, lvl+1) }
"rv=#{g}".pr(lvl)
g
end
class String
def pr(lvl)
print "#{ ' ' * INDENT * lvl}"
puts self
end
end
现在,我们对示例中给出的数据执行此方法
hashify(arr, [1, 2])
lvl=0
positions=[1, 2]
pos=1, positions=[2]
h={"dir1"=>[["root_path", "dir1", "a", "file.jpg"],
["root_path", "dir1", "a", "file2.jpg"],
["root_path", "dir1", "b", "file3.jpg"]],
"dir2"=>[["root_path", "dir2", "c", "file4.jpg"]]}
lvl=1
positions=[2]
pos=2, positions=[]
h={"a"=>[["root_path", "dir1", "a", "file.jpg"],
["root_path", "dir1", "a", "file2.jpg"]],
"b"=>[["root_path", "dir1", "b", "file3.jpg"]]}
lvl=2
positions=[]
parts=[["root_path", "dir1", "a", "file.jpg"],
["root_path", "dir1", "a", "file2.jpg"]]
lvl=2
positions=[]
parts=[["root_path", "dir1", "b", "file3.jpg"]]
这一切都从
def sort\u目录(数组)
开始,然后继续。你试过什么?很好!如果你能一步一步地描述它是如何工作的,那就太好了。