code-reviews

Jakub Holý 2018-07-26T07:34:36.000185Z

Hello, is there a better way to extract an item from a collection based on its attribute than

(some 
  #(when 
      (= (:producer %) "Ferrari") 
      %) 
  cars)
? (Since some returns the result of the test and not the item, I have to wrap the pred in a when to return the item instead of true.) Thanks!

seancorfield 2018-07-26T08:29:03.000181Z

@holyjak (first (filter #(= "Ferrari" (:producer %)) cars)) would work if you don't mind the search going further than the first match (chunking).

Avichal 2018-07-28T09:30:02.000023Z

@seancorfield Thanks for the answer. I have a beginner question. I use the filter first pattern all the time. Sometimes I think if there a function in clojure that does something like “filter-and-return-first-element” ? Is it good idea to make utility function that does something like that and use it or should I always write (first (filter ...) every time?

seancorfield 2018-07-28T16:24:00.000095Z

@avichalp I would just use (first (filter ...)). The only times it might matter are: if you filtering predicate is extremely expensive to run or either the predicate or the sequence being realized have side effects. In those situations you might want more control of the sequence and the filtering operation (and you'd certainly be out of "beginner" territory at that point).

Avichal 2018-07-28T20:19:28.000066Z

Make sense. Thanks for answering.

valtteri 2018-07-26T08:37:36.000267Z

If the collection is not enormous I often find myself transforming it into a map and then doing a lookup. My favourite function atm is:

(defn index-by
  ([idx-fn coll]
   (index-by idx-fn identity coll))
  ([idx-fn value-fn coll]
   (into {} (map (juxt idx-fn value-fn)) coll)))
Which can be used in flexible ways.. For example in this case.
(def cars [{:producer "Ferrari"}
           {:producer "Porsche"}
           {:producer "Mazda"}])

(index-by :producer cars)
=> {"Ferrari" {:producer "Ferrari"},
    "Porsche" {:producer "Porsche"},
    "Mazda" {:producer "Mazda"}}

valtteri 2018-07-26T08:42:04.000254Z

And of course there’s group-by in core which works if there are many Ferraris etc..

seancorfield 2018-07-26T08:58:25.000082Z

☝️:skin-tone-2: Yes, this is a good approach. We have a similar function to index-by at work.

Jakub Holý 2018-07-26T10:00:41.000058Z

Thanks! I had no idea it so so smart as not to continue to filter the rest of the sequence after the current chunk. Neat!

Jakub Holý 2018-07-26T10:01:01.000215Z

thank you all!

2018-07-26T16:01:27.000638Z

clojure.set/index

seancorfield 2018-07-26T16:10:54.000519Z

@hiredman That would return a map where the keys were like {:producer "Ferrari"} right?

2018-07-26T16:12:29.000008Z

it returns something a little more complicated and more general

2018-07-26T16:13:22.000421Z

the values are sets of things with the same indexed values, and the keys are maps where the keys are the keys you index on

2018-07-26T16:14:50.000027Z

{{:producer "Ferrari"} #{{:producer "Ferrari" :some-other-key 1} {:producer "Ferrari" :another-key 5}}}