Clojure에 주어진 값이 목록에 포함되어 있는지 테스트하는 가장 좋은 방법은 무엇입니까?
특히의 행동 contains?
은 현재 나를 혼란스럽게합니다.
(contains? '(100 101 102) 101) => false
분명히 목록을 탐색하고 평등을 테스트하는 간단한 함수를 작성할 수는 있지만 반드시 표준 방법이 있어야합니까?
답변
아, contains?
… 아마도 5 가지 자주 묻는 질문 중 하나 인 Clojure입니다.
컬렉션에 값이 포함되어 있는지 확인 하지 않습니다 . 항목을 검색 할 수 get
있는지, 즉 컬렉션에 키가 있는지 여부를 확인합니다. 이것은 (키와 값 사이에 구분을하지으로 간주 할 수 있습니다) 세트,지도 (그래서에 대한 이해하게 (contains? {:foo 1} :foo)
하다 true
)와 벡터 (그러나 참고 (contains? [:foo :bar] 0)
입니다 true
열쇠가 여기에 인덱스가 문제의 벡터는 “포함”을 않기 때문에, 색인 0
!).
혼란을 가중시키기 위해 호출하는 것이 타당하지 않은 업데이트 : Clojure ≥ 1.5 contains?
경우 간단히 반환합니다 false
. 이것은 (contains? :foo 1)
또한 일어나는 일이다 (contains? '(100 101 102) 101)
. 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
이 경우 시도 할 수있는 네 가지가 있습니다.
-
실제로 벡터 또는 목록이 필요한지 고려하십시오. 당신이 경우 대신 세트를 사용 ,
contains?
작동합니다.(contains? #{:a :b :c} :b) ; = true
-
다음
some
과 같이을 사용 하여 대상을 세트로 묶습니다.(some #{:b} [:a :b :c]) ; = :b, which is truthy
-
잘못된 값 (
false
또는nil
)을 검색하는 경우 기능으로 설정 바로 가기가 작동하지 않습니다 .; will not work (some #{false} [true false true]) ; = nil
이러한 경우에, 당신이해야 사용 내장 술어 기능을 그 값에 대한,
false?
또는nil?
:(some false? [true false true]) ; = true
-
이런 종류의 검색을 많이 해야하는 경우 함수를 작성하십시오 .
(defn seq-contains? [coll target] (some #(= target %) coll)) (seq-contains? [true false true] false) ; = true
또한 여러 대상이 시퀀스에 포함되어 있는지 확인하는 방법 은 Michał의 답변 을 참조하십시오 .