我想要一个像这样的函数:
>(function '(1 2 3 4) '(1 2 3 4 5))
#t
在这种情况下返回#t,因为第一个列表的所有元素都包含在第二个列表中。是否有一个功能可以做到这一点,而不必担心订单?
答案 0 :(得分:3)
在这种情况下,您不是将列表比较为列表,而是将设置,因此使用设计的结构会更有意义这样使用。 Racket在其标准库中提供hash sets。这使得您正在寻找的功能微不足道。
(define (list-subset? a b)
(subset? (list->set a) (list->set b)))
答案 1 :(得分:2)
据我所知,没有内置函数,我相信定义这样的函数的最短方法就是这样。
(define (list-check l1 l2)
(andmap (λ(x) (not (boolean? (memq x l2)))) l1))
答案 2 :(得分:1)
使用memq
可以在小型列表上运行,但是由于我们有可用的哈希表,我们也可以使用它们:
(define (list-check-hash l1 l2)
(define hash (make-hasheq))
(for-each (λ (x) (hash-set! hash x #t)) l2)
(andmap (λ (x) (hash-ref hash x #f)) l1))
;; test
(define test
(let loop ((x 1000000) (acc '()))
(if (zero? x) acc (loop (sub1 x) (cons x acc)))))
(list-check-hash test test) ;==> #t
(list-check-hash test (cdr test)) ;==> #f
当然,您可以选择使用不可变的,因为它更加惯用,并且仍然比memq
快得多:
(define (list-check-hash l1 l2)
(define hash (make-immutable-hasheq (map (λ (x) (cons x #t)) l2)))
(andmap (λ (x) (hash-ref hash x #f)) l1))