问题
I want a function that does something like this:
>(function '(1 2 3 4) '(1 2 3 4 5))
#t
When in this case is returning #t because all elements of the first list are contained in the second list. Is there a function that does that without having to worry about order?
回答1:
So as far as I know there is no built in function for this, and I believe the shortest way to define such function would be something like this.
(define (list-check l1 l2)
(andmap (λ(x) (not (boolean? (memq x l2)))) l1))
回答2:
In this case, you aren't comparing the lists as lists, but as sets, so it would make much more sense to use a structure designed to be used that way. Racket provides hash sets in its standard library. This makes the function you're looking for trivial.
(define (list-subset? a b)
(subset? (list->set a) (list->set b)))
回答3:
Using memq
works swell on small lists, however since we have hash tables available we might as well use them:
(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
Of course you may choose to use immutable ones instead since it's more idiomatic and still a lot faster than 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))
来源:https://stackoverflow.com/questions/29322565/is-there-a-way-to-check-if-all-elements-of-a-list-are-contained-in-another-list