如何在ruby中对文件名进行排序?

时间:2018-07-14 16:06:23

标签: arrays ruby file sorting numbers

是的,它是Is there a natural_sort_by method for Ruby? 的副本,但我认为dawg和Eric在这里更清楚了,至少对我而言,这些答案更为详尽。

我有一个像这样的数组:

arr = ["file1.txt", "file11.txt", "file12.txt", "file2.txt", "file3.txt"]

我希望将其排序如下:

arr = ["file1.txt", "file2.txt", "file3.txt", "file11.txt", "file12.txt"]

我该怎么做?我尝试了sort,但对我来说还不太清楚。

我按这样的大小对文件进行了排序:

files=Dir.entries("./").sort { |f| File.size(f) }.select { |f| File.file?(f) }

2 个答案:

答案 0 :(得分:2)

Eric的答案是只对文件名中的数字进行Natural Sort Order的好方法。如果所有文件名都具有相同的前缀,则可以使用。

如果要添加第二个元素(例如,其中没有数字的文件名),则可以通过创建列表来实现多元素sort _:

filenames = ["file1.txt", "file11.txt", "file12.txt", "file2.txt", "file3.txt","file.txt", "File.txt"]
filenames.sort_by{ |name| [name[/\d+/].to_i, name] }
=> ["File.txt", "file.txt", "file1.txt", "file2.txt", "file3.txt", "file11.txt", "file12.txt"]

sort_by的两个元素实现:

  1. 使用正则表达式name[/\d+/].to_i找到数字的整数值
  2. 如果没有数字或相同数字name,请输入名称。

更强大的功能是,您可以按数字分割整个字符串,并将每个字符串转换为整数:

> "abc123def456gh".split(/(\d+)/).map{ |e| Integer(e) rescue e}
=> ["abc", 123, "def", 456, "gh"]

因此您的自然排序变为:

arr.sort_by{ |s| s.split(/(\d+)/).map{ |e| Integer(e) rescue e}}

因此,现在可以正确处理名称和数字(甚至是名称和数字的倍数):

> arr = ["file1.txt", "file11.txt", "file12.txt", "file2.txt", "file3.txt", "gfile10.txt", "gfile1.txt", "gfile.txt", "file.txt", "afile.txt","afile10.txt","afile2.txt" ]
> arr.sort_by{ |s| s.split(/(\d+)/).map{ |e| Integer(e) rescue e}}
=> ["afile2.txt", "afile10.txt", "afile.txt", "file1.txt", "file2.txt", "file3.txt", "file11.txt", "file12.txt", "file.txt", "gfile1.txt", "gfile10.txt", "gfile.txt"]

答案 1 :(得分:1)

您可以从文件名中提取第一个数字,将其转换为整数并在sort_by中使用它:

filenames = ["file1.txt", "file11.txt", "file12.txt", "file2.txt", "file3.txt"]
filenames.sort_by{ |name| name[/\d+/].to_i }
# ["file1.txt", "file2.txt", "file3.txt", "file11.txt", "file12.txt"]

/\d+/是一个正则表达式,表示“一个1或多个数字的序列”:

"test123"[/\d+/]
# => "123"
"test"[/\d+/]
# => nil

请注意,它仅按数字排序,而忽略其余部分:

["a2", "b1", "z3"].sort_by{ |name| name[/\d+/].to_i }
# => ["b1", "a2", "z3"]