使用常量而不是符号的过滤器代码

时间:2015-12-01 18:57:29

标签: recursion filter scheme racket

(define-struct pizza (size toppings))


;; Constants for testing
(define (meat item)
  (symbol=? 'meat item))

(define (tomatoes item)
  (symbol=? 'tomatoes item))

(define (cheese item)
  (symbol=? 'cheese item))

(define (pepperoni item)
  (symbol=? 'pepperoni item))

(define (hot-peppers item)
  (symbol=? 'hot-peppers item))


(define (count-toppings order topping)
  (cond [(empty? order) 0]
        [else
  (local


    [(define (single-pizza-tops pizza top)
  (length (filter top (pizza-toppings pizza))))
    (define (list-of-nums lop tops)
  (list (single-pizza-tops (first lop) tops)
         (single-pizza-tops (first (rest lop)) tops)
               (single-pizza-tops (first (rest (rest lop))) tops)))]

  (foldr + 0 (list-of-nums order topping)))]))

原来我的代码在定义的常量下运行良好,但是count-toppings不会使用'topping'的符号?

有没有人知道修改我的过滤器功能的方法,这样如果我为浇头输入一个符号,这个代码的工作方式是否相同?

3 个答案:

答案 0 :(得分:0)

Mapfilter可以foldrcons来实施。由于您没有构建列表,因此可以忽略filtermap。通常,虽然将递归映射到高阶函数,但您可以查看类型签名。更难的方法是手动将代码与函数匹配。

Map获取列表,函数或arity,并返回映射到列表中每个元素的函数列表或Haskell notaion中的(a -> b) -> [a] -> [b]

(define (map f L) ;niave implementation pared down for simplicity 
 (if (null? L)
     '()
     (cons (f (car L)) (map f (cdr L)))))

Filter获取arity的谓词和列表,并返回一个满足谓词的列表。或者在Haskell中(a -> bool) -> [a] -> [a]

(define (filter pred L) ;dirro
 (cond ((null? L) '())
       ((pred (car L))
        (cons (car L)
              (filter pred (cdr L))))
       (else (filter pred (cdr L)))))

Foldr接受一个具有arity 2,累加器值和列表的函数,并返回累加器。或者(a -> b -> b) -> b -> [a] -> b在哈斯克尔。

(define (foldr kons knil L) ;ditto
  (if (null? L) 
      knil
      (kons (car L) (foldr kons knil (cdr L)))))

首先,它的诀窍是从你的函数中缓和适合的论点。在你的两个函数中你都有一个cond子句[(empty? topping-list) 0],这表明knil应该是0

count-topping的else语句中你调用+,乍一看建议kons应该是+,但是你的列表不是直接数字,这意味着你必须用lambda语句包装,或者创建辅助功能。 (lambda (x acc) (+ (single-pizza-toppings (pizza-toppings x) atop) acc))

把它放在一起

(define (count-topping alop atop)
  (foldr (lambda (x acc) 
            (+ (single-pizza-toppings (pizza-toppings x) atop)       
               acc))  
         0
         alop))

现在有趣的一个,single-pizza-toppings看起来非常相似。执行lambda语句将包含if语句,如果x是等于topping的符号,则返回1,否则返回0。或者你可以做一些更简单的事情。

(define (single-pizza-toppings topping-list topping)
  (foldr (lambda (x acc)
           (+ 1 acc))
         0
         (filter (lammba (x) (symbol=? x topping))
                 topping-list)))

过滤器过滤器确保每个x前往foldr都是顶部,因此您可以忽略它并添加到累加器。

答案 1 :(得分:0)

假设我们有第一个,我们可以通过

定义第二个
  1. 使用第一个函数,通过map
  2. 计算每个披萨中顶部的出现次数
  3. 计算结果列表的总和
  4. 即,

    (define (count-toppings pizzas topping)
      (sum (map (lambda (p) (single-pizza-toppings (pizza-toppings p) topping)) pizzas)))
    

    对于第一个函数,我们可以使用filter来获取给定顶部的所有出现的列表。
    出现次数是结果的长度:

    (define (single-pizza-toppings toppings topping)
      (length (filter (lambda (t) (symbol=? t topping)) toppings)))
    

    这两个函数都包含将输入转换为我们感兴趣的数据mapfilter,然后是“缩减”,sum和{{1} }。
    这是一种非常常见的模式。

    如果你没有length

    sum

答案 2 :(得分:-2)

看起来你的第一步就是整理一套完整的测试用例。如果您正在使用DrRacket,则可能需要在“选择语言...”菜单中启用“语法测试套件覆盖率”以确保您拥有一组良好的测试。那是第一步......