Is there a way to check if all elements of a list are contained in another list in racket?

假装没事ソ 提交于 2019-12-20 05:41:28

问题


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

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!