2016-12-13 5 views
2

мне нужно, чтобы получить все файлы, присутствующие в каталоге и подкаталогах каталога и каждого файла есть дата добавления к файлу имя, как 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 } 

Который работает, но не кажется хорошим решением, может кто-нибудь, дай мне знать, что будет лучшим способом SOT этого типа в списке?

ответ

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_by является способом быстрее, чем sort.

Чтобы получить нисходящую сортировку, просто позвоните по телефону Enumerable#reverse в конце.

+0

Лучшее решение +1, возможно, требуется« обратная »! – dp7

+0

@ dp7 да, спасибо за отзыв о 'reverse', обновлен. – mudasobwa

+0

Он будет терпеть неудачу, если дата будет такой: 2016-8-03 – Thorin

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 } 
+0

Есть ли способ получить список отсортированных файлов сразу, я имею в виду, что вам не нужно сортировать после получения списка? – Thorin

+0

@Thorin Я думаю, что вам нужно сделать сортировку явно после извлечения имен. – dp7

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]] } 

Вторые элементы массива укажите, как обрабатывать строки, использующие одну и ту же дату.

+0

Кажется лучшим решением, но мне нужно только сортировать по дате, а также нужно получить только те файлы, которые совпадают с шаблоном, могу ли я получить эти файлы напрямую? , как File.open (file_path, "rb"). Grep (/ "id" => 123 /) – Thorin

+0

См. 'Dir.glob': https://ruby-doc.org/core-1.9.3/Dir. html # method-c-glob Вы можете использовать такие шаблоны (не регулярные выражения): 'Dir.glob ('* [0-9] [0-9] [0-9] [0-9] - [0-9 ] [0-9] - [0-9] [0-9] * ') ' – kristinalim