2013-05-17 44 views
2

我想第一个数组进行排序:Ruby - 如何使用sort_by对另一个数组排序一个数组?

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

“请使用Ruby的内置文件类此”?你的意思就像我的回答? –

回答

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"] 
+1

该OP似乎要按扩展名列表major,文件名次要进行排序。 –

+0

@WayneConrad啊,是的,谢谢。 Editted。 – steenslag

+1

这工作。尼斯。 –

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"] 
+0

我加了编辑1来显示结果应该是什么样子。我没有要求按字母顺序排列扩展名上的文件名。我想按照extensions数组的顺序对文件名进行排序。 –

+0

@JamesTesta答案已更新。 :) –

+0

1 - 此结果具有相反类型的文件名 - [“z.html”,“a.html”,“z.txt”,“a.txt”,“z.pdf”,“a.pdf “,”z.rf“,”a.rf“]。 2 - 我想要使用sort_by的答案。 –

-1

没有必要使用File类。只是简单的正则表达式。

filenames.sort_by{|i| i.scan(/\..+$/)[0]} 
+1

这是按扩展名本身排序的,而不是扩展名在'extensions'内的位置。 –

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。要将最后一个未知的扩展名替换为-1extensions.size

+0

'File.extname',就是这样! –

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来自枚举的,并且是在我们收集工具箱一个很好的工具,通过让美的集团的事情“喜欢”的属性。在这种情况下,它将文件的扩展名分组,使用File.extname检索,减去其前导'。'。

重要的是要了解为什么File.extname很重要。由于各种原因,文件可以有多个由'。'分隔的部分。简单地使用split('.')是当时灾难的秘诀,因为拆分后的代码将不得不处理两个以上的字符串。其他文件不包含分隔的'。'在所有。 File.extname进行了合理的尝试,以检索名称中找到的最后的扩展名,所以它是处理文件名和扩展名的更加有道理的方式。从文档:

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来自哈希,并从哈希提取值,在通过按键/参数的顺序这是伟大的这种情况,因为我们可以强制的秩序值与键的顺序相匹配。当你有一个巨大的散列,并希望在一个动作中从中挑选出某些值时,values_at是可以抓取的工具。如果您需要“by-extensions”命令有所不同,请更改extensions,输出将自动反映values_at的结果。

+0

这会丢弃任何不在列表中的扩展名的文件,但如果没有问题,它非常漂亮,易于理解。 –

+1

是的,'File.extname',就是这样!无论如何,我基本上都是noob,我今天刚刚在这里学到了东西。 –

+0

这是一个很酷的答案,但它不使用sort_by。答案可以修改为使用sort_by? –

0
extensions = [".html", ".txt", ".pdf", ".rf"] 
filenames.sort_by { |file_name_string| 
    [ extensions.index(File.extname file_name_string), file_name_string ] 
} 
+0

我尝试了这个,我得到它在文件名首先排序,然后扩展 - [“a.html”,“a.pdf”,“a.rf”,“a.txt”,“z.html”,“ z.pdf“,”z.rf“,”z.txt“]这不是我想要的结果。 –

+0

这非常有趣,我的机器给出了输出'[“a.html”,“z.html”,“a.txt”,“z.txt”,“a.pdf”,“z.pdf”,“a。 rf“,”z.rf“]'...为了得到你指定的输出,我必须在'sort_by'块体内交换数组元素的排序... –

+0

我在Mac上运行rails c Pro和我仍然得到相同的答案。我只是将你的答案剪切并粘贴到导轨控制台中。奇怪,因为你的答案与其他工作的答案类似。 –

1
filenames.sort_by{|f| f.split(".").map{|base, ext| 
    [extensions.index(ext), base] 
}} 
+0

这看起来像它首先对文件名进行排序,然后是给出结果的扩展名 - [“a.html”,“a.pdf”,“a.rf”,“a.txt”,“z.html”,“ z.pdf“,”z.rf“,”z.txt“] - 这不是我想要的。 –

+0

另一方面翻转分机和基地的作品,如 - filenames.sort_by {| f | f.split(“。”)。map {| base,ext | [extensions.index(base),ext]}}。不完全确定原因。 –

相关问题