find first match in a sequence

2,860 views
Skip to first unread message

Jeff Rose

unread,
Feb 10, 2009, 11:18:53 AM2/10/09
to clo...@googlegroups.com
Hi,
Is there a built-in function that will return the first item in a
collection that matches a predicate? (Something equivalent to Ruby's
Enumerable#find...) Seems pretty basic, but I can't find it in the docs.

Thanks,
Jeff

Jeff Rose

unread,
Feb 10, 2009, 11:19:08 AM2/10/09
to Clojure
Well, in case someone else needs the same function and it isn't built-
in, here's what I'm using in the meantime. (Based off of the some
function that comes in core...)

(defn find-first [pred coll]
(when (seq coll)
(if (pred (first coll))
(first coll)
(recur pred (rest coll)))))

Cheers,
Jeff

On Feb 10, 5:18 pm, Jeff Rose <ros...@gmail.com> wrote:
> Hi,
>   Is there a built-in function that will return thefirstitemin a
> collection that matches a predicate?  (Something equivalent to Ruby's
> Enumerable#find...)  Seems pretty basic, but I can'tfindit in the docs.
>
> Thanks,
> Jeff

Mark Fredrickson

unread,
Feb 10, 2009, 11:21:49 AM2/10/09
to clo...@googlegroups.com
Filter is lazy:

http://clojure.org/api#toc228

So you can implement find-first as (first (filter pred coll))

-M
- Mark Fredrickson
mark.m.fr...@gmail.com
http://www.markmfredrickson.com






Stuart Sierra

unread,
Feb 10, 2009, 11:27:08 AM2/10/09
to Clojure
Hi, Jeff, here's how I do it:

user> (def numbers [2 4 6 7 8 9])
#'user/numbers
user> (some #(when (odd? %) %) numbers)
7

-Stuart Sierra

Jeff Rose

unread,
Feb 10, 2009, 12:00:08 PM2/10/09
to clo...@googlegroups.com
Oh cool! I hadn't thought about this aspect of laziness before. I can
see there is some zen here that is worth exploring...

Thanks Mark and Stuart.

-Jeff

Meikel Brandmeyer

unread,
Feb 10, 2009, 1:05:09 PM2/10/09
to clo...@googlegroups.com
Hi,

Am 10.02.2009 um 18:00 schrieb Jeff Rose:

> Oh cool! I hadn't thought about this aspect of laziness before. I
> can
> see there is some zen here that is worth exploring...

Many ways to Rome:

(first (drop-while (complement predicate) coll))

:)

Sincerely
Meikel

Jim - FooBar();

unread,
May 19, 2013, 10:06:50 AM5/19/13
to clo...@googlegroups.com
no need to traverse the entire seq with 'filter' if you only want the 1st match...

(some #(when (odd? %) %)  [2 4 6 7 8 9])
=> 7

Jim


On 19/05/13 13:42, Thumbnail wrote:
... or just (comp first filter) 

((comp first filter) odd? [2 4 6 7 8 9]) 
=> 7
 
--
--
You received this message because you are subscribed to the Google
Groups "Clojure" group.
To post to this group, send email to clo...@googlegroups.com
Note that posts from new members are moderated - please be patient with your first post.
To unsubscribe from this group, send email to
clojure+u...@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en
---
You received this message because you are subscribed to the Google Groups "Clojure" group.
To unsubscribe from this group and stop receiving emails from it, send an email to clojure+u...@googlegroups.com.
For more options, visit https://groups.google.com/groups/opt_out.
 
 

Kelker Ryan

unread,
May 19, 2013, 10:16:18 AM5/19/13
to clo...@googlegroups.com
Try this
user> (first (drop-while even? [2 4 6 7 8 10]))
7

19.05.2013, 23:06, "Jim - FooBar();" <jimpi...@gmail.com>:
> no need to traverse the entire seq with 'filter' if you only want the 1st match...
>
> (some #(when (odd? %) %)О©╫ [2 4 6 7 8 9])
> => 7
>
> Jim
>
> On 19/05/13 13:42, Thumbnail wrote:
>
>> ... or just (comp first filter)О©╫ >

Cedric Greevey

unread,
May 19, 2013, 10:31:49 AM5/19/13
to clo...@googlegroups.com
On Sun, May 19, 2013 at 10:06 AM, Jim - FooBar(); <jimpi...@gmail.com> wrote:
no need to traverse the entire seq with 'filter' if you only want the 1st match...

Pretty sure filter is lazy.

user=> (first (filter odd? (map #(do (println "realized " %) %) (iterate inc 0))))
realized  0
realized  1
1
user=>

Jim - FooBar();

unread,
May 19, 2013, 10:54:53 AM5/19/13
to clo...@googlegroups.com
ha! you cheated with iterate...

try this which is closer to the example...

(first (filter odd? (map #(do (println "realized " %) %)  [2 4 6 7 8 9])))
realized  2
realized  4
realized  6
realized  7
realized  8
realized  9
7

Jim

Jim - FooBar();

unread,
May 19, 2013, 10:55:44 AM5/19/13
to clo...@googlegroups.com
remember the 32-chunked model... :)

Jim

Mikera

unread,
May 19, 2013, 11:06:02 AM5/19/13
to clo...@googlegroups.com, ros...@gmail.com
See the find-first function in my cljutils library:

Note the initial check to see if the collection is Indexed: if it is then it is better to search by index than to create a seq (which causes a lot of unnecessary allocations)

Jonathan Fischer Friberg

unread,
May 19, 2013, 11:20:47 AM5/19/13
to clo...@googlegroups.com
On Sun, May 19, 2013 at 4:54 PM, Jim - FooBar(); <jimpi...@gmail.com> wrote:
ha! you cheated with iterate...

try this which is closer to the example...

(first (filter odd? (map #(do (println "realized " %) %)  [2 4 6 7 8 9])))
realized  2
realized  4
realized  6
realized  7
realized  8
realized  9
7

Jim


=> (some #(when (odd? %) %)

         (map #(do (println "realized" %) %)
              [2 4 6 7 8 9]))
realized 2
realized 4
realized 6
realized 7
realized 8
realized 9
7


;)

In fact, just calling 'first' on a mapped sequence gives the same behaviour:

=> (first (map #(do (println "realized" %) %)

               [2 4 6 7 8 9]))
realized 2
realized 4
realized 6
realized 7
realized 8
realized 9
2

That said, 'some' does avoid realizing the first 32 elements if it's a vec. I still don't
think you should care about that though - that's kind of the point of laziness, to be
able to use map/filter etc without caring about how much is realized.

Jonathan

Nathan Booth

unread,
Mar 21, 2019, 8:14:09 AM3/21/19
to Clojure
I'm glad you pointed this out! On stackoverflow everyone was assuming filter was completely lazy in all cases
Reply all
Reply to author
Forward
0 new messages