【问题标题】:Function to search by values in different types of lists按不同类型列表中的值搜索的功能
【发布时间】:2016-08-31 10:13:06
【问题描述】:

我有 2 种带有键值对的列表:

(define pairs1 (list (list 1 2)(list 10 20)(list 100 200)))
(define pairs2 (list (cons 1 2)(cons 10 20)(cons 100 200)))

我想用一个函数在两种列表中按值搜索。我尝试了以下操作(一个中的“cdr”和其他 fn 中的“第二”),但它们每个都使用一个列表:

(define (assoc_val1 val spair)
  (for/list ((item spair) #:when (equal? (cdr item) val))
      item))

(define (assoc_val2 val spair)
  (for/list ((item spair) #:when (equal? (second item) val))
      item))

我可以有一个对这两种列表都有效的函数吗?另外,是否有一个很好的链接来解释 (list 1 2)、(cons 1 2) 和 '(1 2) 之间的区别?


编辑:修改@Sylwester 提供的答案,以下函数可以检测并处理两个列表:

(define (assoc2* haystack needle [is-equal? equal?] )
  (if (list? (car haystack))
      (findf (λ (e) (is-equal? needle (second e))) haystack)
      (findf (λ (e) (is-equal? needle (cdr e))) haystack)
      ))

(assoc2* pairs1 20)
(assoc2* pairs2 20)

输出:

'(10 20)
'(10 . 20)

【问题讨论】:

标签: list scheme racket


【解决方案1】:

只需添加#:accessor作为关键字参数或可选参数:

;; Fully compatible with assoc but allows for searching any part 
(define (assoc* haystack needle [is-equal? equal?] #:accessor [accessor car])
  (findf (λ (e) (is-equal? needle (accessor e))) haystack))

(assoc* pairs1 20 #:accessor cadr) ; ==> (10 20)
(assoc* pairs2 20 #:accessor cdr)  ; ==> (10 . 20)

【讨论】:

  • 代码能否检测出它是哪种类型的列表并应用相关功能?
  • @mso 这取决于.. 假设您有一个带有对值的关联,例如。 '((0 . (0 0)) (1 . (0 1)) (2 . (1 0)) (3 . (1 1)))。如您所知,(0 . (0 0))(0 0 0) 相同,那么如何确定元素是对还是列表?您不能,但是如果您知道这些值是 never 对,那么您可以这样做,但这将不再是一般过程。
  • 请在上面的问题中查看我对您的代码的修改。作品因为 (cons 1 2) 给出了 false 与 "list?"功能。
  • @mso 尝试使用(assoc2* '((0 . (0 0)) (1 . (0 1)) (2 . (1 0)) (3 . (1 1))) '(1 0))。正确答案是(2 . (1 0)),但它返回#f。因此,我的声明是,为了做到这一点,您不能再将对作为值,并且它不再是一般程序。 (assoc* '((0 . (0 0)) (1 . (0 1)) (2 . (1 0)) (3 . (1 1))) '(1 0) #:accessor cdr) 做正确的事。
  • 感谢您的解释。
猜你喜欢
  • 2021-03-27
  • 1970-01-01
  • 2021-01-29
  • 1970-01-01
  • 1970-01-01
  • 2012-09-04
  • 1970-01-01
  • 2011-03-04
相关资源
最近更新 更多