在 Clojure 中测试列表是否包含给定值的最佳方法是什么?
特别是,contains?目前的行为让我感到困惑:
contains?
(contains? '(100 101 102) 101) => false
我显然可以编写一个简单的函数来遍历列表并测试是否相等,但是肯定有一个标准的方法来做到这一点?
啊,contains?......据说是前五个常见问题解答之一:Clojure。
它不 检查 集合是否包含值;它检查一个项目是否可以被检索到,get或者换句话说,一个集合是否包含一个键。这对于集合(可以被认为不区分键和值)、映射(所以(contains? {:foo 1} :foo)是true)和向量(但请注意,因为这里的键(contains? [:foo :bar] 0)是true索引,并且所讨论的向量确实“包含”索引0!)。
get
(contains? {:foo 1} :foo)
true
(contains? [:foo :bar] 0)
0
更令人困惑的是,在调用没有意义的情况下contains?,它只是简单地返回false;这就是发生在(contains? :foo 1) and (contains? '(100 101 102) 101)中的事情。 更新: 在 Clojurecontains?中,当提交不支持预期“关键成员资格”测试的类型的对象时,会抛出 1.5 次。
false
(contains? :foo 1)
(contains? '(100 101 102) 101)
做你想做的事情的正确方法如下:
; most of the time this works (some #{101} '(100 101 102))
在搜索一堆项目中的一个时,您可以使用更大的集合;搜索false/时nil,可以使用false?/ nil?-- 因为(#{x} x)返回x,所以(#{nil} nil)是nil;当搜索其中一些可能是false或的多个项目之一时nil,您可以使用
nil
false?
nil?
(#{x} x)
x
(#{nil} nil)
(some (zipmap [...the items...] (repeat true)) the-collection)
(请注意,项目可以zipmap在任何类型的集合中传递。)
zipmap