我想对第一个数组进行排序:
filenames = ["z.pdf", "z.txt", "a.pdf", "z.rf", "a.rf","a.txt", "z.html", "a.html"]
通过以下文件的扩展数组:
extensions = ["html", "txt", "pdf", "rf"]
使用sort_by
。但是当我尝试:
filenames.sort_by { |x| extensions.index x.split('.')[1] }
我明白了:
["a.html", "z.html", "z.txt", "a.txt", "a.pdf", "z.pdf", "z.rf", "a.rf"]
扩展名为“txt”和“rf”的文件名未排序。我试图弄清sort_by
如何使用元组进行排序,但无法找到sort_by
的源代码。
如何使用sort_by
按另一个数组对一个数组进行排序?
编辑:
结果如下:
["a.html", "z.html", "a.txt", "z.txt", "a.pdf", "z.pdf", "a.rf", "z.rf"]
答案 0 :(得分:3)
sorted = filenames.sort_by do |filename|
extension = File.extname(filename).gsub(/^\./, '')
[
extensions.index(extension) || -1,
filename,
]
end
p sorted
# => ["a.html", "z.html", "a.txt", "z.txt", "a.pdf", "z.pdf", "a.rf", "z.rf"]
这使用了这样的事实:数组的排序顺序由它们的元素的排序顺序决定,按照它们的定义顺序。这意味着如果sort_by
返回一个数组,则数组的第一个元素是主要排序顺序,第二个元素是辅助排序顺序,依此类推。我们利用它来按扩展名major,filename minor进行排序。
如果扩展名不在列表中,则此代码会根据||= -1
将其放在首位。要将未知扩展名设置为最后,请将-1
替换为extensions.size
。
答案 1 :(得分:3)
怎么样:
>> filenames.sort.group_by{ |s| File.extname(s)[1..-1] }.values_at(*extensions).flatten
[
[0] "a.html",
[1] "z.html",
[2] "a.txt",
[3] "z.txt",
[4] "a.pdf",
[5] "z.pdf",
[6] "a.rf",
[7] "z.rf"
]
group_by
来自Enumerable,在我们的收藏工具箱中是一个不错的工具,让我们按“喜欢”属性对事物进行分组。在这种情况下,它会对文件的扩展名进行分组,使用File.extname
检索,减去其前导“。”。
了解 File.extname
为何非常重要。由于各种原因,文件可以包含由“。”分隔的多个部分。在这一点上简单地使用split('.')
是灾难的一个方法,因为拆分后的代码必须处理两个以上的字符串。其他文件不包含分隔符'。'一点都不File.extname
合理地尝试检索名称中找到的 last 扩展名,因此处理文件名和扩展名更为明智。来自文档:
File.extname("test.rb") #=> ".rb"
File.extname("a/b/d/test.rb") #=> ".rb"
File.extname("foo.") #=> ""
File.extname("test") #=> ""
File.extname(".profile") #=> ""
File.extname(".profile.sh") #=> ".sh"
values_at
来自Hash,并按照传入的键/参数的顺序从哈希中提取值。这对于这种情况很有用,因为我们可以强制值的顺序与钥匙的顺序。如果你有一个巨大的哈希并想在一个动作中从中挑选某些值,values_at
就是抓取的工具。如果您需要将“按扩展程序”排序设置不同,请更改extensions
,输出将自动反映values_at
的结果。
答案 2 :(得分:3)
按扩展数组的索引排序,然后按文件名:
排序filenames = ["z.pdf", "z.txt", "a.pdf", "z.rf", "a.rf","a.txt", "z.html", "a.html"]
extensions = ["html", "txt", "pdf", "rf"]
p sorted = filenames.sort_by{|fn| [extensions.index(File.extname(fn)[1..-1]), fn]} #[1..-1] chops off the dot
#=> ["a.html", "z.html", "a.txt", "z.txt", "a.pdf", "z.pdf", "a.rf", "z.rf"]
答案 3 :(得分:1)
filenames.sort_by{|f| f.split(".").map{|base, ext|
[extensions.index(ext), base]
}}
答案 4 :(得分:0)
filenames = ["z.pdf", "z.txt", "a.pdf", "z.rf", "a.rf","a.txt", "z.html", "a.html"]
extensions = ["html", "txt", "pdf", "rf"]
extensions.each_with_object([]){|k,ob| ob << filenames.find_all {|i| File.extname(i)[1..-1] == k }.sort}.flatten
#=> ["a.html", "z.html", "a.txt", "z.txt", "a.pdf", "z.pdf", "a.rf", "z.rf"]
答案 5 :(得分:0)
extensions = [".html", ".txt", ".pdf", ".rf"]
filenames.sort_by { |file_name_string|
[ extensions.index( File.extname file_name_string ), file_name_string ]
}
答案 6 :(得分:-1)
无需使用File类。只是简单明了的正则表达式。
filenames.sort_by{|i| i.scan(/\..+$/)[0]}