Сортировка списка хэшэков в Racket - PullRequest
0 голосов
/ 04 октября 2018

Я создаю функцию 'sort-mail' в Racket, которая берет список hash-eq и сортирует их по ключу данных.Входные данные определяются следующим образом:

 (define test-dates
    '("Sun, 10 Sep 2017 09:48:44 +0200"
      "Wed, 13 Sep 2017 17:51:05 +0000"
      "Sun, 10 Sep 2017 13:16:19 +0200"
      "Tue, 17 Nov 2009 18:21:38 -0500"
      "Wed, 13 Sep 2017 10:40:47 -0700"
      "Thu, 14 Sep 2017 12:03:35 -0700"
      "Wed, 18 Nov 2009 02:22:12 -0800"
      "Sat, 09 Sep 2017 13:40:18 -0700"
      "Tue, 26 Oct 2010 15:11:06 +0200"
      "Tue, 17 Nov 2009 18:04:31 -0800"
      "Mon, 17 Oct 2011 04:15:12 +0000"
      "Sun, 16 Oct 2011 23:12:02 -0500"
      "Mon, 11 Sep 2017 14:41:12 +0100"))

 (define test-hashes (map (lambda (x) (hasheq 'Date x)) test-dates))

Я пытался ответить на вопрос на этот вопрос, но я не думаю, что это то, что я ищу.До сих пор я пытаюсь отсортировать их, используя следующее:

 (define (sort-mail test-hashes)
    (sort test-hashes #:key car <))

К сожалению, я получаю эту ошибку: автомобиль: ожидается нарушение контракта: пара?учитывая: 'hasheq ((Данные. "Ср, 13 сентября 2017 г. 17:51:05 +0000"

) Я не совсем понимаю, как должно выглядеть мое утверждение сортировки, поэтому любые рекомендации будут хорошими.Спасибо!

1 Ответ

0 голосов
/ 06 октября 2018

Есть две проблемы.

Во-первых, причиной сообщения об ошибке является то, что sort вызывает car (функция #:key) для каждого элемента test-hashes список, и каждый из этих элементов является хэш-таблицей, а не списком.car ожидает список, следовательно, ошибка.

Ваша функция #:key должна извлечь дату из хеш-таблицы.hash-ref делает это.Итак, вот первая попытка sort-mail:

(define (sort-mail hash-tables)
  (define (date-of ht) (hash-ref ht 'Date))
  (sort hash-tables #:key date-of string<?))

Это подводит нас ко второй проблеме, которая является функцией сравнения дат.Обратите внимание, что функция сравнения выше string<?, а не <.Это связано с тем, что значение, связанное с ключом Date в каждой хэш-таблице, является строкой.Вызов string<? позволяет избежать ошибки типа времени выполнения, но даты сортируются в неправильном порядке:

> (sort-mail test-hashes)
'(#hasheq((Date . "Mon, 11 Sep 2017 14:41:12 +0100"))
  #hasheq((Date . "Mon, 17 Oct 2011 04:15:12 +0000"))
  #hasheq((Date . "Sat, 09 Sep 2017 13:40:18 -0700"))
  #hasheq((Date . "Sun, 10 Sep 2017 09:48:44 +0200"))
  #hasheq((Date . "Sun, 10 Sep 2017 13:16:19 +0200"))
  #hasheq((Date . "Sun, 16 Oct 2011 23:12:02 -0500"))
  #hasheq((Date . "Thu, 14 Sep 2017 12:03:35 -0700"))
  #hasheq((Date . "Tue, 17 Nov 2009 18:04:31 -0800"))
  #hasheq((Date . "Tue, 17 Nov 2009 18:21:38 -0500"))
  #hasheq((Date . "Tue, 26 Oct 2010 15:11:06 +0200"))
  #hasheq((Date . "Wed, 13 Sep 2017 10:40:47 -0700"))
  #hasheq((Date . "Wed, 13 Sep 2017 17:51:05 +0000"))
  #hasheq((Date . "Wed, 18 Nov 2009 02:22:12 -0800")))

Как видно, даты сортируются по алфавиту, а не по дате.Действительно, вам нужна функция #:key, которая возвращает дату, представленную таким образом, чтобы ее можно было легко сравнить с другими датами.

Строки вашей даты хранятся в формате RFC-2822 .Я быстро просмотрел документацию по Racket и не нашел стандартной библиотечной функции для анализа строк даты RFC-2822.Некоторое прибегание к поиску появилось в этом блоге Tero Hasu , который включает функцию для преобразования строк даты RFC-2822 во времена Unix.«Unix time» - это время, представленное в виде количества секунд с 1 января 1970 года. Это число, поэтому вы можете сравнить его с <.

Вот код, вставленный из блога Теро Хасу:

(require (prefix-in s. srfi/19))

(define (rfc2822->unix-time s) ;; string -> integer
  (let ((d (s.string->date s "~a, ~d ~b ~Y ~H:~M:~S ~z")))
    (s.time-second (s.date->time-utc d))))

И наконец, вот исправленное sort-mail:

(define (sort-mail hash-tables)
  (define (ht->unix-time ht) (rfc2822->unix-time (hash-ref ht 'Date)))
  (sort hash-tables #:key ht->unix-time <))

> (sort-mail test-hashes)
'(#hasheq((Date . "Tue, 17 Nov 2009 18:21:38 -0500"))
  #hasheq((Date . "Tue, 17 Nov 2009 18:04:31 -0800"))
  #hasheq((Date . "Wed, 18 Nov 2009 02:22:12 -0800"))
  #hasheq((Date . "Tue, 26 Oct 2010 15:11:06 +0200"))
  #hasheq((Date . "Sun, 16 Oct 2011 23:12:02 -0500"))
  #hasheq((Date . "Mon, 17 Oct 2011 04:15:12 +0000"))
  #hasheq((Date . "Sat, 09 Sep 2017 13:40:18 -0700"))
  #hasheq((Date . "Sun, 10 Sep 2017 09:48:44 +0200"))
  #hasheq((Date . "Sun, 10 Sep 2017 13:16:19 +0200"))
  #hasheq((Date . "Mon, 11 Sep 2017 14:41:12 +0100"))
  #hasheq((Date . "Wed, 13 Sep 2017 10:40:47 -0700"))
  #hasheq((Date . "Wed, 13 Sep 2017 17:51:05 +0000"))
  #hasheq((Date . "Thu, 14 Sep 2017 12:03:35 -0700")))
...