【问题标题】:How to use maps and filters in Racket如何在 Racket 中使用地图和过滤器
【发布时间】:2019-11-20 04:23:48
【问题描述】:

我在尝试在 Racket 中使用地图和过滤器时遇到问题:

我正在使用一个结构来表示一个数据表,我知道我需要将该表提供给一个映射函数以进行迭代,然后过滤掉非勤奋的条目以获取最终列表,但我没有想法如何从我的结构中获取我需要的信息或地图和过滤器的外观......

这就是我所拥有的:

#lang racket

(struct worker (name work study ent))

(define workers(list
                     (worker '(bill) '(none) '(medium) '(none))
                     (worker '(jill) '(high) '(low) '(medium))
                     (worker '(tim) '(vhigh) '(none) '(vhigh))
                     (worker '(gary) '(medium) '(high) '(medium))
                     (worker '(samantha) '(vlow) '(vlow) '(medium))
                     (worker '(holly) '(vlow) '(low) '(low))
                     (worker '(ryan) '(low) '(low) '(low))
                     (worker '(quin) '(low) '(medium) '(vlow))
                     (worker '(lisa) '(medium) '(vlow) '(high))
                     (worker '(jennifer) '(low) '(low) '(vlow))
                     (worker '(jeff) '(high) '(low) '(high))
                     (worker '(george) '(medium) '(vhigh) '(medium))
                     (worker '(beth) '(none) '(none) '(low))
                     (worker '(maria) '(vlow) '(medium) '(low))
                     (worker '(simon) '(medium) '(high) '(high))
                     ))

(define convert
  (lambda (input)
    (match (input
           ('none 0)
           ('vlow 1)
           ('low 2)
           ('medium 3)
           ('high 4)
           ('vhigh 5)
           )
          )
    )
)

(define (hardworker workers)
  (map(lambda(workers)...

感谢任何帮助。

【问题讨论】:

    标签: racket


    【解决方案1】:
    #lang racket
    (require rackunit)
    

    代表工人

    请注意,由于您输入了'( ... )(带引号的括号),因此每个字段都是[Listof Symbol],而不仅仅是this 答案中表示的符号本身。每个结构都会产生“选择器函数”,可以提取字段的值。

    (worker-ent (worker '(quin) '(low) '(medium) '(vlow))) 
    ; => '(vlow). 
    
    (first '(vlow)) 
    ; => 'vlow. 
    

    如果我们只使用符号来表示结构的字段,那就是:

    (define workers
      (list   ; name     work    study   ent
       (worker 'bill     'none   'medium 'none)
       (worker 'jill     'high   'low    'medium)
       (worker 'tim      'vhigh  'none   'vhigh)
       (worker 'gary     'medium 'high   'medium)
       (worker 'samantha 'vlow   'vlow   'medium)
       (worker 'holly    'vlow   'low    'low)
       (worker 'ryan     'low    'low    'low)
       (worker 'quin     'low    'medium 'vlow)
       (worker 'lisa     'medium 'vlow   'high)
       (worker 'jennifer 'low    'low    'vlow)
       (worker 'jeff     'high   'low    'high)
       (worker 'george   'medium 'vhigh  'medium)
       (worker 'beth     'none   'none   'low)
       (worker 'maria    'vlow   'medium 'low)
       (worker 'simon    'medium 'high   'high)))
    

    事实上,写下每个字段代表的内容及其类型是明智的:

    (struct worker (name work study ent) #:transparent)
    ; A Worker is a (worker Symbol Amount Amount Amount)
    ; interpretation. name is the name of the worker, work, study and ent are
    ; the Amount that represents the work, study and entertainment done by the worker. 
    
    ; Amount is one of
    ; - 'none
    ; - 'vlow
    ; - 'low
    ; - 'medium
    ; - 'high
    ; - 'vhigh
    ; interpretation. represents amount of something done. 
    

    转换函数

    convert 将“金额”枚举放入订单中,但是用于match 的语法有问题。这是带有测试的完整定义:

    ; convert : Amount -> Natural
    ; The ordering number of each Amount.
    (define convert
      (lambda (input)
        (match input
          ['none   0]
          ['vlow   1]
          ['low    2]
          ['medium 3]
          ['high   4]
          ['vhigh  5])))
    
    (check-equal? (convert 'none)   0)
    (check-equal? (convert 'vlow)   1)
    (check-equal? (convert 'low)    2)
    (check-equal? (convert 'medium) 3)
    (check-equal? (convert 'high)   4)
    (check-equal? (convert 'vhigh)  5)
    

    注意1:我们可以通过使用index-of来避免使用匹配,如下所示:

    (define (convert.v2 i)
      (index-of '(none  vlow low medium high vhigh) i))
    
    (check-equal? (convert.v2 'none)   0)
    (check-equal? (convert.v2 'vlow)   1)
    (check-equal? (convert.v2 'low)    2)
    (check-equal? (convert.v2 'medium) 3)
    (check-equal? (convert.v2 'high)   4)
    (check-equal? (convert.v2 'vhigh)  5)
    

    金额谓词

    为了解决这个问题,我们需要知道金额为“至少高”和“不超过中等”意味着什么,因此我们做出以下谓词:

    ; at-least-high? : Amount -> Boolean
    ; is `a` at least High?
    (define (at-least-high? a)
      (>= (convert a) 4))
    
    (check-false (at-least-high? 'none))
    (check-false (at-least-high? 'vlow))
    (check-false (at-least-high? 'low))
    (check-false (at-least-high? 'medium))
    (check-true  (at-least-high? 'high))
    (check-true  (at-least-high? 'vhigh))
    

    ; no-more-than-medium? : Amount -> Boolean
    ; is `a` not more than Medium?
    (define (no-more-than-medium? a)
      (<= (convert a) 3))
    
    (check-true  (no-more-than-medium? 'none))
    (check-true  (no-more-than-medium? 'vlow))
    (check-true  (no-more-than-medium? 'low))
    (check-true  (no-more-than-medium? 'medium))
    (check-false (no-more-than-medium? 'high))
    (check-false (no-more-than-medium? 'vhigh))
    

    注意 2:我们可以简单地检查对我们的条件有效的数量枚举成员,在这种情况下我们不需要convert

    (define (at-least-high?.v2 a)
      (or (symbol=? a 'high) (symbol=? a 'vhigh)))
    
    (define (no-more-than-medium?.v2 a)
      (or (symbol=? a 'none) (symbol=? a 'vlow)
          (symbol=? a 'low) (symbol=? a 'medium))) 
    
    

    勤奋?谓词

    对一个人来说,努力工作意味着什么?它只是已经定义的两个谓词的合取:

    ; hardworker? : Worker -> Boolean
    ; Hard workers do at least high amount of work and
    ; have no more than medium amount of entertainment.
    (define (hardworker? w)
      (and (at-least-high? (worker-work w)) 
           (no-more-than-medium? (worker-ent w))))
    
    (check-true  (worker 'bill 'none 'medium 'none))
    (check-false (worker 'jill 'high 'low    'medium))
    

    注意 3:如果我有您对工人的定义,我必须将 (worker-work w)(worker-ent w)first 包装起来才能将符号从列表中提取出来。

    最后,workers 列表可以使用hardworker? 进行filtered。

    注意 4:我们不需要 map 来遍历列表,在幕后对列表进行过滤。

    ; hardworker : [List-of Worker] -> [List-of Worker]
    ; Only keep hard-workers. 
    (define (hardworker workers)
      (filter hardworker? workers))
    
    (check-equal? (hardworker workers) (list (worker 'jill 'high 'low 'medium)))
    (check-equal? (hardworker (rest (rest workers))) empty)
    

    小版本

    我们可以使用 lambda 将所有内容整合到一个函数中:

    (define (hardworker.v2 workers)
      (filter (λ (w) (and (member (worker-work w) '(high vhigh)) 
                          (member (worker-ent w)  '(none vlow low medium))))
              workers))
    

    【讨论】:

    • 我希望我能给你更多的 +1。这非常清楚,谢谢你的笔记。
    【解决方案2】:
    #lang racket
    (define-struct worker (name work study ent) #:transparent #:mutable)
    
    (define workers-list
      (list
       (make-worker 'bill 'none 'medium 'none)
       (make-worker 'jill 'high 'low 'medium)
       (make-worker 'tim 'vhigh 'none 'vhigh)
       (make-worker 'gary 'medium 'high 'medium)))
    ; work hard
    (filter (lambda (w) (equal? 'high (worker-work w))) workers-list)
    ; not wrok hard
    (filter (lambda (w) (not (equal? 'high (worker-work w)))) workers-list)
    
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2015-11-04
      • 1970-01-01
      • 1970-01-01
      • 2017-02-28
      • 1970-01-01
      • 1970-01-01
      • 2017-08-15
      • 1970-01-01
      相关资源
      最近更新 更多