【问题标题】:Sorting a hasheq list in Racket在 Racket 中对 hasheq 列表进行排序
【发布时间】:2018-10-03 21:49:20
【问题描述】:

我正在 Racket 中创建一个函数 'sort-mail',它接收一个 hash-eq 列表并根据它们的 Data 键对它们进行排序。输入是这样定义的:

 (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 <))

不幸的是,我收到了这个错误: 汽车:合同违约 预期:对? 给定:'hasheq((数据。“2017 年 9 月 13 日星期三 17:51:05 +0000”

我对我的排序语句应该是什么样子感到很困惑,所以任何指导都会很棒。谢谢!

【问题讨论】:

    标签: hashmap hashtable racket


    【解决方案1】:

    有两个问题。

    首先,错误消息的原因是sorttest-hashes 列表的每个元素上调用car#:key 函数),并且这些元素中的每一个都是哈希表,而不是列表。 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&lt;?而不是&lt;。这是因为每个哈希表中与Date 键关联的值是一个字符串。调用 string&lt;? 可以避免运行时类型错误,但日期的排序顺序错误:

    > (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 的this blog post,其中包括将 RFC-2822 日期字符串转换为 Unix 时间的函数。 “Unix 时间”是表示为自 1970 年 1 月 1 日以来的秒数的时间。这是一个数字,因此您可以将其与 &lt; 进行比较。

    这是从 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")))
    

    【讨论】:

      猜你喜欢
      • 2023-01-30
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-10-12
      • 2015-09-13
      • 2012-01-15
      • 1970-01-01
      相关资源
      最近更新 更多