【问题标题】:Scheme: Counting Structures方案:计数结构
【发布时间】:2014-05-18 02:36:37
【问题描述】:
(count-by-type
(list
(make-animal "Slytherin" "snake" (make-date 2013 8 23))
(make-animal "Toby" "dog" (make-date 2014 3 20))
(make-animal "Curly" "dog" (make-date 2014 1 18))
(make-animal "Maximus" "cat" (make-date 2013 10 7))
(make-animal "Mia" "cat" (make-date 2013 10 7))))
=> (list (list 2 "cat") (list 2 "dog") (list 1 "snake"))

;; A Date is a structure (make-date y m d), where
;; y is positive integer (year),
;; m is an integer between 1 and 12 (month),
;; d is an integer between 1 and 31 (day of the month).
(define-struct date (year month day))
;; An Animal is a structure (make-structure n t a), where
;; n is a nonempty string (name of animal),
;; t is a nonempty string (type of animal),
;; a is a Date (date animal arrived at the shelter).
(define-struct animal (name type arrival))

注意:适用的数据结构如上。

所以我正在尝试制作一个函数(在使用 Dr. Racket 的 Scheme 中),它使用一个 Animal 结构列表并生成一个列表列表。

生成列表中的元素采用 (list number type) 形式,其中 type 是动物的类型,number 是消耗列表中该动物类型的编号。

这对我来说是可行的,但这就是问题所在: -> 列表需要按降序排列 -> 更糟糕的是,如果任意数量的列表对之间存在平局,则按字母排序被利用了。

注意:我希望只使用不包括 build-list 和 lambda 的抽象列表函数来解决这个问题(因为我希望加强我在没有高级抽象函数的情况下解决此类问题的能力)

记住这一点,我知道这个问题将使用抽象函数 map、filter 和 foldr,但不太清楚如何。

感谢任何帮助。

【问题讨论】:

  • 我不太明白你的限制——你想使用哪些功能,你想避免哪些功能?
  • @uselpa 想要避免使用 lambda 和 build-list。
  • 为什么要避免lambda?既然你想创建一个函数,你无论如何都需要lambda
  • @uselpa 我想先熟练使用本地定义的函数,然后再使用 lambda...

标签: list data-structures scheme


【解决方案1】:

如果您执行(map animal-type list-of-animals),您会得到一个列表,其中仅包含("snake" "dog" "cat" "dog" "cat") 之类的类型

我想你的列表可以混合(就像我的例子一样)所以如果你(sort list-of-animal-types string>?)你有一个排序列表降序

鉴于列表至少有一个元素:

(let rec ((cur (car sorted-list-of-animal-types))
          (cnt 1)
          (lst (cdr sorted-list-of-animal-types))
          (acc '()))
  (cond ((equal? cur <??>) (rec cur (add1 <??>) <??> acc))
        (else (rec <??> 1 <??> (cons (list cnt cur) <??>)))))

这将产生一个列表升序计数。可以通过折叠来做到这一点,但它的行数可能不会比使用命名let 少。

如果再次排序:

(sort list-of-animal-types-and-counts (lambda (x y) (>= (car x) (car y)))

Racket 中的sort 稳定。这意味着如果您在列表中有两个相同的数量,它们将以原始顺序结束。原始顺序是动物升序,因此结果按计数降序排列,然后按名称升序排列。

我猜你的过程可以通过使用let 将它们链接在一起来存储中间体以使表达式更短且更具可读性。

使用散列,您可以只通过未排序的列表一次,然后生成一个列表,然后使用 sepcial 排序函数排序,该函数先按计数排序,然后按动物类型排序。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2019-03-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-03-07
    • 1970-01-01
    • 2015-12-15
    相关资源
    最近更新 更多