在 Racket 中对 hasheq 列表进行排序
Sorting a hasheq list in Racket
我正在 Racket 中创建一个函数 'sort-mail',它接受一个 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))
我已尝试按照 this 问题的答案进行操作,但我认为这不是我要查找的内容。到目前为止,我正在尝试使用以下方法对它们进行排序:
(define (sort-mail test-hashes)
(sort test-hashes #:key car <))
不幸的是,我收到了这个错误:
car:contract违规
预期:一对?
给出:'hasheq((数据。"Wed, 13 Sept 2017 17:51:05 +0000"
我很困惑我的排序语句应该是什么样子,所以任何指导都会很好。谢谢!
有两个问题。
首先,错误消息的原因是 sort
在 test-hashes
列表的每个元素上调用 car
(#:key
函数),并且每个这些元素是散列-table,而不是列表。 car
需要一个列表,因此会出现错误。
您的 #:key
函数需要从散列 table 中提取日期。 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<?
而不是 <
。这是因为每个散列 table 中与 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
函数,该函数 returns 日期的表示方式可以很容易地与其他日期进行比较。
您的日期字符串以 Tero Hasu 称为 RFC-2822. I did a quick search of the Racket documentation and didn't find a standard library function to parse RFC-2822 date strings. Some googling turned up this blog post 的格式存储,其中包括将 RFC-2822 日期字符串转换为 Unix 时间的函数。 “Unix 时间”是表示自 1970 年 1 月 1 日以来的秒数的时间。这是一个数字,因此您可以将它与 <
.
进行比较
这是从 Tero Hasu 的博客中粘贴的代码:
(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")))
我正在 Racket 中创建一个函数 'sort-mail',它接受一个 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))
我已尝试按照 this 问题的答案进行操作,但我认为这不是我要查找的内容。到目前为止,我正在尝试使用以下方法对它们进行排序:
(define (sort-mail test-hashes)
(sort test-hashes #:key car <))
不幸的是,我收到了这个错误: car:contract违规 预期:一对? 给出:'hasheq((数据。"Wed, 13 Sept 2017 17:51:05 +0000"
我很困惑我的排序语句应该是什么样子,所以任何指导都会很好。谢谢!
有两个问题。
首先,错误消息的原因是 sort
在 test-hashes
列表的每个元素上调用 car
(#:key
函数),并且每个这些元素是散列-table,而不是列表。 car
需要一个列表,因此会出现错误。
您的 #:key
函数需要从散列 table 中提取日期。 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<?
而不是 <
。这是因为每个散列 table 中与 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
函数,该函数 returns 日期的表示方式可以很容易地与其他日期进行比较。
您的日期字符串以 Tero Hasu 称为 RFC-2822. I did a quick search of the Racket documentation and didn't find a standard library function to parse RFC-2822 date strings. Some googling turned up this blog post 的格式存储,其中包括将 RFC-2822 日期字符串转换为 Unix 时间的函数。 “Unix 时间”是表示自 1970 年 1 月 1 日以来的秒数的时间。这是一个数字,因此您可以将它与 <
.
这是从 Tero Hasu 的博客中粘贴的代码:
(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")))