对这些类型的字符串进行排序的最佳方法是什么?

时间:2016-12-13 06:28:35

标签: ruby-on-rails arrays ruby sorting

我需要将所有文件都存在于目录和子目录中,并且每个文件的日期都附加到文件名,如 product_log_2016-11-17.txt

获取我使用的目录中的文件列表

all_logs = Dir["#{Rails.root}/log/product_logs/**/*.txt"]

并返回完整路径文件(我已从每个条目中删除了系统路径:

[
  "/log/product_logs/new_2/product_log_2016-11-17.txt",
  "/log/product_logs/new_2/products_log_2016-11-03.txt",
  "/log/product_logs/new_1/products_log_2016-10-04.txt",
  "/log/product_logs/new_1/product_log_2016-11-17.txt",
  "/log/product_logs/new_1/products_log_2016-11-03.txt"
]

但是我希望像这样按日期排序:

[
  "/log/product_logs/new_2/product_log_2016-11-17.txt",
  "/log/product_logs/new_1/product_log_2016-11-17.txt",
  "/log/product_logs/new_2/products_log_2016-11-03.txt",
  "/log/product_logs/new_1/products_log_2016-11-03.txt",
  "/log/product_logs/new_1/products_log_2016-10-04.txt"
]

我试过这样的话:

all_logs.sort{|a, b|b.split("/").last.split("_").last.split(".").first <=>a.split("/").last.split("_").last.split(".").first }

哪个有效,但似乎不是一个好的解决方案,任何人都可以告诉我什么是最好的方式来输入这种类型的列表?

3 个答案:

答案 0 :(得分:5)

▶ input.sort_by { |i| [i[/\d{4}-\d{1,2}-\d{1,2}/], i[/\d+/]] }
#⇒ [
#    [0] "/log/product_logs/new_1/products_log_2016-10-04.txt",
#    [1] "/log/product_logs/new_1/products_log_2016-11-03.txt",
#    [2] "/log/product_logs/new_2/products_log_2016-11-03.txt",
#    [3] "/log/product_logs/new_1/product_log_2016-11-17.txt",
#    [4] "/log/product_logs/new_2/product_log_2016-11-17.txt"
# ]

与给出的答案相比有两个优点:

  • new_???号码和
  • 对同一日期排序
  • sort_bysort更快。

要接收降序排序,最后只需将呼叫链接到Enumerable#reverse

答案 1 :(得分:1)

你可以试试这个:

all_logs = [
  "/log/product_logs/new_2/product_log_2016-11-17.txt",
  "/log/product_logs/new_2/products_log_2016-11-03.txt",
  "/log/product_logs/new_1/products_log_2016-10-04.txt",
  "/log/product_logs/new_1/product_log_2016-11-17.txt",
  "/log/product_logs/new_1/products_log_2016-11-03.txt"
]

all_logs.sort { |a, b| b.split("/").last.to_date <=> a.split("/").last.to_date }

答案 2 :(得分:1)

你可以这样做:

# Returns:
# 
# [
#    ["/log/product_logs/new_2/product_log_2016-11-17.txt", "2016-11-17"],
#    ...
# ]
date_mapping = array.map { |s| [s, s.match(/\d{4}-\d{2}-\d{2}/)[0]] }

# Sort arrays, and then get the first elements.
date_mapping.sort { |a, b| [b[1], a[0]] <=> [a[1], b[0]] }.map(&:first)

请注意以下两行之间的区别:

date_mapping.sort { |a, b| [b[1], a[0]] <=> [a[1], b[0]] }
date_mapping.sort { |a, b| [b[1], b[0]] <=> [a[1], a[0]] }

数组的第二个元素指定应如何处理使用相同日期的字符串。