Racket / Scheme中的抽象列表函数 - 列表中的元素出现次数

时间:2014-11-17 01:21:29

标签: list lambda scheme racket

所以我现在被困在一个“简单?”在Racket中的功能。它正在使用lambda语言的中级学生。

对此的一些限制是不允许递归,也不允许本地函数。这是简单而简单的抽象列表函数。

这个函数应该做的是接收一个数字列表,并输出一对数组,其中每一对都有第一个元素作为数字,第二个元素是它在列表中出现的数字。

示例:

   (1 1 2 3) => ((1 2) (2 1) (3 1))
   (2 3 4 3) => ((2 1) (3 2) (4 1))

我有一个函数,通过输入一个数字列表和一个数字来产生出现次数:

(define (occurrences lon n)
    (length (filter (lambda (x) (= x n)) lon)))

我的做法显然是错误的:

(define (num-pairs-occurrences lon)
    (list (lambda (x) (map (occurrences lon x) (remove x lon)) x))

我认为上述方法可行,但显然我的lambda放置不正确。有什么想法吗?

2 个答案:

答案 0 :(得分:3)

它比你想象的要复杂一些。您可能已经注意到,我们必须删除输出列表中的重复元素。为此,最好定义一个remove-duplicates辅助函数(也使用抽象列表函数) - 实际上,这是常见的,它是Racket中的内置函数,但在当前语言设置中不可用:

(define (remove-duplicates lst)
  (foldr (lambda (e acc)
           (if (member e acc)
               acc
               (cons e acc)))
         '()
         lst))

现在可以使用抽象列表函数轻松编写解决方案:

(define (num-pairs-occurrences lon)
  (map (lambda (e) (list e (occurrences lon e)))
       (remove-duplicates lon)))

以上可能会以不同的顺序返回并输出列表,但这样可以。在你问之前:是的,我们需要帮助函数。如果没有它,请不要求解决方案......

答案 1 :(得分:0)

一个简单,独立的解决方案是:

(define (num-pairs-occurences lst)
  (foldl (lambda (e r) 
           (if (or (null? r) (not (= (caar r) e)))
               (cons (list e 1) r)
               (cons (list e (add1 (cadar r))) (cdr r))))
         null
         (sort lst >)))

基本上,您首先对列表进行排序,然后折叠它。如果得到的元素(e)与结果列表(r)的第一个元素相同,则递增计数,否则向r添加新的子列表。

如果按>(降序)排序,实际上可以使用foldl,这样可以提高内存效率。如果按<(升序)排序,则需要使用效率较低的foldr

相关问题