ruby переупорядочивает массив дат с частями строки, сохраняющими пустую строку - PullRequest
1 голос
/ 15 июня 2019

У меня есть этот массив дат, который содержит пустые строки, и я хочу переупорядочить его двумя способами, и в каждом случае пустая строка должна всегда находиться перед массивом.

[" ", "2018-10-01", "2019", " ",  "2019-06-20", "2019-06", "2019-10", "2019-01-01", "2017", "2018-05", "2018", "2018-05-10",  " "]

Первый результат:переупорядочить таким образом

["", "", "", "2019-10-01", "2019-10", "2019-06-20", "2019-06", "2019", "2018-01-01", "2018-05", "2018-05-10", "2017"]

Второй способ, которым я хочу иметь возможность переупорядочить его таким образом:

[" ", " ", " ", "2017", "2018-01-01", "2019-06-20", "2019-06", "2019-10-01", "2019-10", "2019"]

Я попробовал код ниже, но я не сделалполучите желаемый результат.

  ["", "", "", "2019-10-01", "2019-10", "2019-06-20", "2019-06", "2019", "2018-01-01", "2018-05", "2018-05-10", "2017"].sort_by { |date| parts = date.split('-').map(&:to_i) }

update

будет ли возможность сортировки по возрастанию выйти в этом порядке.yy-mm-dd, затем yy-mm, затем просто год, что означает сортировку по возрастанию, должна быть в этой форме [" ", " ", " ", "2017","2018-05-10", "2018-05", "2018-10-01", "2018", "2019-01-01", "2019-06-20", "2019-06", "2019-10", "2019"].Таким образом, это не обычная сортировка по возрастанию, но она основана на шаблоне, который приводит к приведенному выше порядку.

Тот же шаблон применяется к сортировке по убыванию.

Ответы [ 2 ]

2 голосов
/ 15 июня 2019

Решение № 1 - нормальная сортировка

Вы можете сначала разбить список на основании того, что строка пуста или нет.Затем отсортируйте все существующие даты и объедините их вместе.

dates = [" ", "2018-10-01", "2019", " ",  "2019-06-20", "2019-06", "2019-10", "2019-01-01", "2017", "2018-05", "2018", "2018-05-10",  " "]

asc = ->(a, b) { a <=> b }
desc = ->(a, b) { b <=> a }

blank, present = dates.partition(&:blank?)
result1 = blank + present.sort(&desc)
#=> [" ", " ", " ", "2019-10", "2019-06-20", "2019-06", "2019-01-01", "2019", "2018-10-01", "2018-05-10", "2018-05", "2018", "2017"]
result2 = blank + present.sort(&asc)
#=> [" ", " ", " ", "2017", "2018", "2018-05", "2018-05-10", "2018-10-01", "2019", "2019-01-01", "2019-06", "2019-06-20", "2019-10"]

Примечание: Это просто сортирует массив в алфавитном порядке.Что хорошо, если вы используете формат yyyy-mm-dd (с начальными нулями, если только одна цифра).Если даты поставляются в другом формате, вы хотите сначала преобразовать их в дату.

Решение № 2 - примите самое высокое значение для пропущенного месяца или дня

strings = [" ", "2018-10-01", "2019", " ",  "2019-06-20", "2019-06", "2019-10", "2019-01-01", "2017", "2018-05", "2018", "2018-05-10",  " "]

array_to_date = lambda do |(year, month, day)|
  month ||= 12
  day ||= 31

  begin
    Date.new(year, month, day)
  rescue ArgumentError
    raise unless (1..12).cover? month
    raise unless (1..31).cover? day
    array_to_date.call([year, month, day - 1])
  end
end

date_regex = /\A(\d{4})(?:-(\d{2})(?:-(\d{2}))?)?\z/
yyyy_mm_dd = ->(date_string) { date_regex.match(date_string).captures.compact.map(&:to_i) }
string_to_date = yyyy_mm_dd >> array_to_date

asc = ->(a, b) { string_to_date.call(a) <=> string_to_date.call(b) }
desc = ->(a, b) { string_to_date.call(b) <=> string_to_date.call(a) }

dates, non_dates = strings.partition(&date_regex.method(:match?))
result1 = non_dates + dates.sort(&desc)
#=> [" ", " ", " ", "2019", "2019-10", "2019-06", "2019-06-20", "2019-01-01", "2018", "2018-10-01", "2018-05", "2018-05-10", "2017"]
result2 = non_dates + dates.sort(&asc)
#=> [" ", " ", " ", "2017", "2018-05-10", "2018-05", "2018-10-01", "2018", "2019-01-01", "2019-06-20", "2019-06", "2019-10", "2019"]

Примечание: Это не самое эффективное решение, поскольку строки должны преобразовываться каждый раз, когда вызывается блок #sort.Если вы работаете с большими массивами, вы можете сначала преобразовать все значения и сохранить их в хеше.Затем найдите их при сортировке.

Текущее регулярное выражение также позволяет передавать строки типа "0000-00-00", возможно, вы захотите сделать его более конкретным.

2 голосов
/ 15 июня 2019
arr = [" ", "2018-10-01", "2019", " ",  "2019-06-20", "2019-06", "2019-10",
       "2019-01-01", "2017", "2018-05", "2018", "2018-05-10",  " "]

Сортировка по возрастанию:

def sort_asc(arr)
  arr.sort
end

sort_asc(arr)
  #=> [" ", " ", " ",
  #    "2017",
  #    "2018", "2018-05", "2018-05-10", "2018-10-01",
  #    "2019", "2019-01-01", "2019-06", "2019-06-20", "2019-10"]

Сортировка по убыванию:

def sort_dsc(arr)
  arr.sort_by { |s| s == ' ' ? '99' : s }.reverse
end

sort_dsc(arr)
  #=> [" ", " ", " ",
  #    "2019-10", "2019-06-20", "2019-06", "2019-01-01", "2019",
  #    "2018-10-01", "2018-05-10", "2018-05", "2018",
  #    "2017"]
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...