有没有办法检查列表中的所有元素是否包含在球拍的另一个列表中?

时间:2015-03-28 21:01:22

标签: list scheme racket

我想要一个像这样的函数:

>(function '(1 2 3 4) '(1 2 3 4 5))
#t

在这种情况下返回#t,因为第一个列表的所有元素都包含在第二个列表中。是否有一个功能可以做到这一点,而不必担心订单?

3 个答案:

答案 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))