[data-structures] Clojure에 목록에 특정 값이 포함되어 있는지 테스트

Clojure에 주어진 값이 목록에 포함되어 있는지 테스트하는 가장 좋은 방법은 무엇입니까?

특히의 행동 contains?은 현재 나를 혼란스럽게합니다.

(contains? '(100 101 102) 101) => false

분명히 목록을 탐색하고 평등을 테스트하는 간단한 함수를 작성할 수는 있지만 반드시 표준 방법이 있어야합니까?



답변

아, contains?… 아마도 5 가지 자주 묻는 질문 중 하나 인 Clojure입니다.

컬렉션에 값이 포함되어 있는지 확인 하지 않습니다 . 항목을 검색 할 수 get있는지, 즉 컬렉션에 키가 있는지 여부를 확인합니다. 이것은 (키와 값 사이에 구분을하지으로 간주 할 수 있습니다) 세트,지도 (그래서에 대한 이해하게 (contains? {:foo 1} :foo)하다 true)와 벡터 (그러나 참고 (contains? [:foo :bar] 0)입니다 true열쇠가 여기에 인덱스가 문제의 벡터는 “포함”을 않기 때문에, 색인 0!).

혼란을 가중시키기 위해 호출하는 것이 타당하지 않은 contains?경우 간단히 반환합니다 false. 이것은 (contains? :foo 1) 또한 일어나는 일이다 (contains? '(100 101 102) 101). 업데이트 : Clojure ≥ 1.5 contains?에서 의도 된 “키 멤버쉽”테스트를 지원하지 않는 유형의 객체를 건네 주면 던집니다.

당신이하려는 일을하는 올바른 방법은 다음과 같습니다.

; most of the time this works
(some #{101} '(100 101 102))

여러 항목 중 하나를 검색 할 때 더 큰 세트를 사용할 수 있습니다. 검색 할 때 false/ nil당신은 사용할 수 있습니다 false?/ nil?– 때문에 (#{x} x)반환 x, 따라서 (#{nil} nil)이다 nil; false또는 여러 항목 중 하나를 검색 nil할 때

(some (zipmap [...the items...] (repeat true)) the-collection)

(항목은 zipmap모든 유형의 컬렉션 으로 전달 될 수 있습니다 .)


답변

동일한 목적을위한 표준 유틸리티는 다음과 같습니다.

(defn in? 
  "true if coll contains elm"
  [coll elm]  
  (some #(= elm %) coll))


답변

.methodName 구문을 사용하여 Java 메소드를 항상 호출 할 수 있습니다.

(.contains [100 101 102] 101) => true


답변

조금 늦었다는 것을 알고 있습니다.

(contains? (set '(101 102 103)) 102)

마지막으로 clojure 1.4에서 true 출력 🙂


답변

(not= -1 (.indexOf '(101 102 103) 102))

작동하지만 아래가 더 좋습니다.

(some #(= 102 %) '(101 102 103)) 


답변

가치가있는 것은 목록에 대한 포함 함수를 간단하게 구현 한 것입니다.

(defn list-contains? [coll value]
  (let [s (seq coll)]
    (if s
      (if (= (first s) value) true (recur (rest s) value))
      false)))


답변

벡터 또는 목록이 있고 이 포함되어 있는지 확인하려는 contains?경우 작동하지 않습니다. Michał은 이미 그 이유를 설명했습니다 .

; does not work as you might expect
(contains? [:a :b :c] :b) ; = false

이 경우 시도 할 수있는 네 가지가 있습니다.

  1. 실제로 벡터 또는 목록이 필요한지 고려하십시오. 당신이 경우 대신 세트를 사용 , contains?작동합니다.

    (contains? #{:a :b :c} :b) ; = true
  2. 다음some 과 같이을 사용 하여 대상을 세트로 묶습니다.

    (some #{:b} [:a :b :c]) ; = :b, which is truthy
  3. 잘못된 값 ( false또는 nil)을 검색하는 경우 기능으로 설정 바로 가기가 작동하지 않습니다 .

    ; will not work
    (some #{false} [true false true]) ; = nil

    이러한 경우에, 당신이해야 사용 내장 술어 기능을 그 값에 대한, false?또는 nil?:

    (some false? [true false true]) ; = true
  4. 이런 종류의 검색을 많이 해야하는 경우 함수를 작성하십시오 .

    (defn seq-contains? [coll target] (some #(= target %) coll))
    (seq-contains? [true false true] false) ; = true

또한 여러 대상이 시퀀스에 포함되어 있는지 확인하는 방법 은 Michał의 답변 을 참조하십시오 .