contains

50 views
Skip to first unread message

Mark Volkmann

unread,
Jan 23, 2009, 3:32:37 PM1/23/09
to clo...@googlegroups.com
This must be something I learned months ago and then forgot ... embarassing!
What's the easiest way to determine if a sequence contains a given value?
I thought there would be something like this: (include? [2 4 7] 4) -> true
That doesn't exist.
I know I can do this: (some #{4} [2 4 7])
Having to create a set seems overkill.

--
R. Mark Volkmann
Object Computing, Inc.

Justin Johnson

unread,
Jan 23, 2009, 3:39:58 PM1/23/09
to clo...@googlegroups.com
On Fri, Jan 23, 2009 at 2:32 PM, Mark Volkmann <r.mark....@gmail.com> wrote:

This must be something I learned months ago and then forgot ... embarassing!
What's the easiest way to determine if a sequence contains a given value?
I thought there would be something like this: (include? [2 4 7] 4) -> true
That doesn't exist.
I know I can do this: (some #{4} [2 4 7])
Having to create a set seems overkill.

user=> (contains? [1 2 3] 1)
true

Chouser

unread,
Jan 23, 2009, 3:45:12 PM1/23/09
to clo...@googlegroups.com
On Fri, Jan 23, 2009 at 3:39 PM, Justin Johnson
<ajustin...@gmail.com> wrote:
> On Fri, Jan 23, 2009 at 2:32 PM, Mark Volkmann <r.mark....@gmail.com>
> wrote:
>>
>> This must be something I learned months ago and then forgot ...
>> embarassing!
>> What's the easiest way to determine if a sequence contains a given value?
>> I thought there would be something like this: (include? [2 4 7] 4) -> true
>> That doesn't exist.

Sure it does:

user=> (require 'clojure.contrib.seq-utils)
nil
user=> (clojure.contrib.seq-utils/includes? [2 4 7] 4)
true

:-)

>> I know I can do this: (some #{4} [2 4 7])
>> Having to create a set seems overkill.

It's not! It's beautiful and succinct. And it let's you test for any
of several values, and then tells you which it found:

user=> (some #{3 4 5} [2 4 7])
4

> user=> (contains? [1 2 3] 1)
> true

This is doing something different:

user=> (contains? [2 4 7] 7)
false

That's telling you that the vector has no value at index 7. The docs
try to explain this:

user=> (doc contains?)
-------------------------
clojure.core/contains?
([coll key])
Returns true if key is present in the given collection, otherwise
returns false. Note that for numerically indexed collections like
vectors and Java arrays, this tests if the numeric key is within the
range of indexes. 'contains?' operates constant or logarithmic time;
it will not perform a linear search for a value. See also 'some'.

--Chouser

Mark Volkmann

unread,
Jan 23, 2009, 3:47:46 PM1/23/09
to clo...@googlegroups.com

That doesn't do what you think it does. For example,

(contains? [2 4 7] 4) -> false

The doc string includes this: "Note that for numerically indexed


collections like vectors and Java arrays, this tests if the numeric

key is within the range of indexes." So it doesn't compare the
values.

I'd like to use it with strings like this to determine if a letter is a vowel:

(contains? "aeiou" letter)

but that doesn't work either.

Mark Volkmann

unread,
Jan 23, 2009, 3:50:40 PM1/23/09
to clo...@googlegroups.com
On Fri, Jan 23, 2009 at 2:45 PM, Chouser <cho...@gmail.com> wrote:
>
> On Fri, Jan 23, 2009 at 3:39 PM, Justin Johnson
> <ajustin...@gmail.com> wrote:
>> On Fri, Jan 23, 2009 at 2:32 PM, Mark Volkmann <r.mark....@gmail.com>
>> wrote:
>>>
>>> This must be something I learned months ago and then forgot ...
>>> embarassing!
>>> What's the easiest way to determine if a sequence contains a given value?
>>> I thought there would be something like this: (include? [2 4 7] 4) -> true
>>> That doesn't exist.
>
> Sure it does:
>
> user=> (require 'clojure.contrib.seq-utils)
> nil
> user=> (clojure.contrib.seq-utils/includes? [2 4 7] 4)
> true
>
> :-)

Thanks! It's too bad something this basic isn't in the core.

>>> I know I can do this: (some #{4} [2 4 7])
>>> Having to create a set seems overkill.
>
> It's not! It's beautiful and succinct. And it let's you test for any
> of several values, and then tells you which it found:
>
> user=> (some #{3 4 5} [2 4 7])
> 4

Well ... I agree that it's beautiful and succinct IF you want to test
multiple values. I just think there should be a simpler way to test
for one value that is in the core.

>> user=> (contains? [1 2 3] 1)
>> true
>
> This is doing something different:
>
> user=> (contains? [2 4 7] 7)
> false
>
> That's telling you that the vector has no value at index 7.

Yeah, I just figured that out while you were composing your reply.

Thanks!

Chouser

unread,
Jan 23, 2009, 3:51:01 PM1/23/09
to clo...@googlegroups.com
On Fri, Jan 23, 2009 at 3:47 PM, Mark Volkmann
<r.mark....@gmail.com> wrote:
>
> (contains? "aeiou" letter)
>
> but that doesn't work either.

user=> (some (set "aeiou") "dn'tndthsstinkngvwls")
\i

Or, if you must,

user=> (clojure.contrib.seq-utils/includes? "aeiou" \o)
true

--Chouser

Mark Volkmann

unread,
Jan 23, 2009, 4:04:20 PM1/23/09
to clo...@googlegroups.com
On Fri, Jan 23, 2009 at 2:51 PM, Chouser <cho...@gmail.com> wrote:
>
> On Fri, Jan 23, 2009 at 3:47 PM, Mark Volkmann
> <r.mark....@gmail.com> wrote:
>>
>> (contains? "aeiou" letter)
>>
>> but that doesn't work either.
>
> user=> (some (set "aeiou") "dn'tndthsstinkngvwls")
> \i

Why does this work

(some (set "aeiou") "e")

but this doesn't

(some #{"aeiou"} "e")

I thought (set ...) was equivalent to #{...}.

> Or, if you must,
>
> user=> (clojure.contrib.seq-utils/includes? "aeiou" \o)
> true

--

Stuart Halloway

unread,
Jan 23, 2009, 4:12:39 PM1/23/09
to clo...@googlegroups.com
Hi Mark,

set takes a single argument, a coll, and #{} is a literal form that
can have a variable number of args.

To make them equivalent:

(set "aeiou")
-> #{\a \e \i \o \u}

#{(seq "aeiou")}
-> #{(\a \e \i \o \u)}

Stuart

Chouser

unread,
Jan 23, 2009, 4:13:44 PM1/23/09
to clo...@googlegroups.com
On Fri, Jan 23, 2009 at 4:04 PM, Mark Volkmann
<r.mark....@gmail.com> wrote:
>
> Why does this work
>
> (some (set "aeiou") "e")
>
> but this doesn't
>
> (some #{"aeiou"} "e")
>
> I thought (set ...) was equivalent to #{...}.

(hash-set ...) is equivalent to #{...}

'set' takes a single collection as an argument, which it will treat as
a seq and pour into a hash-set, so above the string behaves as a seq
of chars, and each char becomes an item in the set:

user=> (set "aeiou")


#{\a \e \i \o \u}

On the other hand, hash-set and #{} expect several args, each of which
becomes an item in the set:

user=> (hash-set "aeiou")
#{"aeiou"}

--Chouser

Message has been deleted

Mark Volkmann

unread,
Jan 23, 2009, 4:13:47 PM1/23/09
to clo...@googlegroups.com
I'm trying to implement pig latin using only what's in core in the
simplest way possible.
Does anyone see a simpler way?
I'm not happy with using three functions (some, set and str) to
determine if a letter is a vowel.

(defn pig-latin [word]
(let [first-letter (first word)]
(if (some (set "aeiou") (str first-letter))
(str word "ay")
(str (subs word 1) first-letter "ay"))))

(println (pig-latin "red")) -> "edray"
(println (pig-latin "orange")) -> "orangeay"

Chouser

unread,
Jan 23, 2009, 4:43:13 PM1/23/09
to clo...@googlegroups.com
On Fri, Jan 23, 2009 at 4:13 PM, Mark Volkmann
<r.mark....@gmail.com> wrote:
>
> I'm trying to implement pig latin using only what's in core in the
> simplest way possible.
> Does anyone see a simpler way?
> I'm not happy with using three functions (some, set and str) to
> determine if a letter is a vowel.

I'm not quite sure what your criteria is, but here are a couple other options:

; String.contains and an extra 'subs'
(defn pig-latin [word]
(let [first-letter (subs word 0 1)]
(if (.contains "aeiou" first-letter)


(str word "ay")
(str (subs word 1) first-letter "ay"))))

; String.contains with destructuring
(defn pig-latin [[first-letter :as word]]
(if (.contains "aeiou" (str first-letter))


(str word "ay")
(str (subs word 1) first-letter "ay")))

; Strings collapse quivering in fear when destructuring and regex join forces
(defn pig-latin [word]
(if-let [[_ a b] (re-find #"^([^aeiou])(.*)" word)]
(str b a "ay")
(str word "ay")))

--Chouser

Mark Volkmann

unread,
Jan 23, 2009, 4:52:03 PM1/23/09
to clo...@googlegroups.com

Thanks! I like the second option the best.
I hope option three was written to be funny. I both laugh and cry when
looking at that. ;-)

wubbie

unread,
Jan 23, 2009, 4:57:59 PM1/23/09
to Clojure
(some (set "aeiou") "e")
is equiv to
(some #{\a \e \i \o \u} "e")
-> \e

Finally, I can answer, instead of keep asking...

-sun


On Jan 23, 4:04 pm, Mark Volkmann <r.mark.volkm...@gmail.com> wrote:
Reply all
Reply to author
Forward
0 new messages