球拍:我试图建立一个函数,返回与键

时间:2017-04-27 07:27:47

标签: racket

我有一个列表(列表(列表键值)...),我试图建立一个函数,返回与键相关的所有值。

我认为我可以使用匹配构造但是没有任何成功。

#lang racket

; should return a list starting with key, otherwise #f 
(define (match-key lst key)
  (match lst
      [(list key val) value]
      [_ #f]))
; testing data
(define test-lst 
  (list
   (list 'title "Lorem title") 
   (list 'price 999.99)
   (list 'colour "red")
   ))

(eq? "Lorem title" (match-key test-lst 'title)) ; should return #t
(eq? "Another lorem" (match-key test-lst 'title)) ; should return #f
(eq? 999.99 (match-key test-lst 'price)) ; should return #t
(eq? 111.11 (match-key test-lst 'price)) ; should return #f

1 个答案:

答案 0 :(得分:3)

在结构上,模式(list key val)(list (list key val) ...)不同。由于您将后者作为字典的结构,因此在过程match-key中匹配的唯一子句将成为最后一个,其中_表示与任何语法对象匹配的模式。

要使用match过滤键值对列表并返回所有关联值,您可以执行以下操作:

(define (filter/match lst key)
  (let ([has-key? (lambda (l) (equal? (car l) key))])
    (match lst
      ['()                   '()]
      [(cons (? has-key?) b) (cons (cadar lst) (filter/match b key))]
      [(cons a b)            (filter/match b key)])))

例如,

;; test data
(define test-lst 
  (list (list 'title "title1") 
        (list 'price 999.99)
        (list 'title "title2")
        (list 'colour "red")))

(filter/match test-lst 'title)
=> '("title1" "title2")

或者,您可以使用for/list更简单地实现此目的,如下所示:

(define (get-val lst key)
  (for/list ([l lst]
             #:when (equal? (car l) key))
    (cadr l)))

例如:

> (get-val test-lst 'title)
'("title1" "title2")    

您还可以查看可用于dictionaries的各种内置程序。例如,使用dict-ref,您可以执行以下操作:

(dict-ref test-lst 'title #f)
=> '("title1")
(dict-ref test-lst 'rand-key #f)
=> #f

这将返回第一个键实例的值(因此,与键关联的所有值都不匹配)。如果未找到任何匹配项,则返回#f