有没有办法检查一个列表的所有元素是否包含在球拍的另一个列表中?
Is there a way to check if all elements of a list are contained in another list in racket?
我想要一个函数来做这样的事情:
>(function '(1 2 3 4) '(1 2 3 4 5))
#t
When 在这种情况下返回 #t,因为第一个列表的所有元素都包含在第二个列表中。有没有不用担心顺序的函数?
据我所知,没有内置函数,我相信定义此类函数的最短方法是这样的。
(define (list-check l1 l2)
(andmap (λ(x) (not (boolean? (memq x l2)))) l1))
使用 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))
在这种情况下,您不是将列表作为 lists 进行比较,而是作为 sets,因此它会更有意义使用设计为以这种方式使用的结构。 Racket 在其标准库中提供 hash sets。这使得您正在寻找的功能变得微不足道。
(define (list-subset? a b)
(subset? (list->set a) (list->set b)))
我想要一个函数来做这样的事情:
>(function '(1 2 3 4) '(1 2 3 4 5))
#t
When 在这种情况下返回 #t,因为第一个列表的所有元素都包含在第二个列表中。有没有不用担心顺序的函数?
据我所知,没有内置函数,我相信定义此类函数的最短方法是这样的。
(define (list-check l1 l2)
(andmap (λ(x) (not (boolean? (memq x l2)))) l1))
使用 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))
在这种情况下,您不是将列表作为 lists 进行比较,而是作为 sets,因此它会更有意义使用设计为以这种方式使用的结构。 Racket 在其标准库中提供 hash sets。这使得您正在寻找的功能变得微不足道。
(define (list-subset? a b)
(subset? (list->set a) (list->set b)))