获取列表列表中的第二项

时间:2021-02-16 13:23:17

标签: scheme lisp

我有一个通过嵌套 cons 生成的列表,该列表创建了这样的结构 - 我在下面创建了一个示例列表。

(define lst '(((name . test) . 15) ))

我希望稍后使用 assq 过滤名称,然后访问每个名称的值。例如,在上面的示例中,我希望能够做一些时尚的事情(伪代码):

if (cdr (assq 'name lst2) == test, print the value [15]

我该怎么做?我只能执行 (assq 'name (car (lst))) 来取回正确的名称,但随后我无法访问值 15

1 个答案:

答案 0 :(得分:1)

您需要编写自己的类似 assoc 的过程。要么有一个关键功能来提取你想要比较的东西,要么有一个通用的测试功能可以做到这一点,或者两者兼而有之。这是允许通用测试功能的一个:

(define (asst o l test)
  ;; test is called on o and the element of l in that order
  (if (null? l)
      #f
      (let ((f (car l))
            (r (cdr l)))
        (if (test o f)
            f
            (asst o r test)))))

现在

> (asst 'name '(((name . test) . 15))
        (lambda (o el)
          (eqv? o (car (car el)))))
'((name . test) . 15)

如果您想对列表进行更一般的测试,那么有一个名为 find 的通用函数可以执行此操作。 find is defined in SRFI 1,但很容易实现:

(define (find pred? l)
  (cond
    ((null? l)
     #f)
    ((pred? (first l))
     (first l))
    (else
     (find pred? (rest l)))))

给定 find 然后很容易编写一个函数来查找例如结构中的特定键和值:

(define (findfv l field value)
  (find (λ (e)
          (and (eqv? (car (car e)) field)
               (eqv? (cdr (car e)) value)))
        l))

现在

> (findfv '(((name . fred) . 12) ((feature . legs) 8) ((name . josephine) . 15)) 'name 'josephine)
'((name . josephine) . 15)
> (findfv '(((name . fred) . 12) ((feature . legs) 8) ((name . josephine) . 15)) 'feature 'legs)
'((feature . legs) 8)

(在 CL 中提供的 assoc 函数允许测试和关键选项)

相关问题