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

List Racket/Scheme中的抽象列表函数-列表中元素出现的数量,list,lambda,scheme,racket,List,Lambda,Scheme,Racket,所以我现在被一个“简单”的功能卡在了球拍上。它使用的是中级学生的lambda语言 这方面的一些限制是不允许递归,局部函数也不允许递归。它是简单明了的抽象列表函数 这个函数要做的是接收一个数字列表,并输出一个对列表,其中每对都有第一个元素作为数字,第二个元素是列表中出现的数字 示例: (1 1 2 3) => ((1 2) (2 1) (3 1)) (2 3 4 3) => ((2 1) (3 2) (4 1)) 我有一个函数,通过输入一个数字列表和一个数字来产生出现的次

所以我现在被一个“简单”的功能卡在了球拍上。它使用的是中级学生的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没有放好。有什么想法吗?

这比你想象的要复杂一些。您可能已经注意到,我们必须删除输出列表中的重复元素。为此,我们最好定义一个
remove duplicates
helper函数(也使用抽象列表函数)——事实上,这非常常见,是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)))

上面的代码可能会以不同的顺序返回和输出列表,但没关系。在你问之前:是的,我们确实需要帮助函数。请不要要求没有它的解决方案…

一个简单、独立的解决方案应该是:

(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
,这会更节省内存。如果您按
OP排序,则不允许递归,因此删除重复项的定义(如果该语言中尚未提供)将是禁止的。我设法创建了一个与删除重复项类似的函数,但没有递归。所以它现在工作得很好。非常感谢。后来,我对如何实现从列表中删除元素感到困惑。@E46我用
删除重复项的无递归实现更新了我的答案。我希望这就是你想要的,老师不应该用这些人为的问题限制学生,在现实生活中,你可以使用语言中可用的任何工具来解决问题是的,这就是我想要的。而且,是的,我相信完全一样。但在某种意义上,它有助于理解和应用抽象列表函数,因为我真的会使用递归,因为它更简单,更容易实现。