Getting the largest key vector in a map vector

I have a map vector that looks like this:

(def game-vec [{:game 1 :start 123456} {:game 2 :start 523456} {:game 3 :start 173456} {:game 1 :start 123456} {:game 1 :start 523456} {:game 2 :start 128456} {:game 3 :start 123256}]) 

I would like to take the most time :start for each :game . What is the best way to do this?

+4
source share
6 answers

Here is another solution

 user=> (map #(apply max-key :start %) (vals (group-by :game game-vec))) ({:game 1, :start 523456} {:game 2, :start 523456} {:game 3, :start 173456}) 
+5
source
 (into {} (for [[game times] (group-by :game game-vec)] {game (apply max (map :start times))})) 
+3
source

One way is to get all the games from the vector.

maybe something like:

 (defn game-keys [from] (set (map (fn [x] (:game x)) from))) 

Now we have all the unique games that are stored somewhere, now for each of them we want to get the highest start value. Sorting can be useful if we filter out the right games.

 (defn games [key from] (filter (fn [x] (= (:game x) key)) from)) 

So, we can get the games that we need, now we need only the highest of them

 (defn max-start [lst] (first (sort (fn [xy] (> (:start x) (:start y))) lst))) 

So now we can do:

 (map (fn [x] (max-start (games x game-vec))) (game-keys game-vec)) 

However, this is just one way to do, probably the best ways to do, depending on the definition of the best.

+2
source

I came up with this:

 (defn max-start-per-game [coll] (into {} (map (fn [[kv]] [k (apply max (map :start v))]) (group-by :game game-vec)))) => (max-start-per-game game-vec) {1 523456, 2 523456, 3 173456} 

The idea is to get all the data for the game in one place, and then take out the data to run. Then just do max.

More general version:

 (defn collect [coll sum-key collect] (into {} (map (fn [[kv]] [k (map :start v)]) (group-by :game game-vec)))) (defn no-good-name [coll f key1 key2] (into {} (map (fn [[kv]] [k (fv)]) (collect coll key1 key2))) (no-good-name game-vec #(apply max %) :game :start) => {1 523456, 2 523456, 3 173456} 

(using the costum function (called fmap somewhere in contrib) to display across all map values ​​would be better, but you can do it yourself)

+2
source

Iterate over my last solution using the idea of ​​max function from @nickik. I am convinced that there is a one-liner here :-)

 (reduce (fn [mx] (assoc m (:game x) (max (:start x) (or (m (:game x)) 0)))) {} game-vec) 
+1
source

Functionally very similar to Julian Chastang code and uses reduce I have:

 (defn max-start-per-game [games] (reduce (fn [res {:keys [game start]}] (let [cur-start (get res game 0) max-start (max start cur-start)] (assoc res game max-start))) {} games)) 
 user=> (max-start-per-game game-vec) {3 173456, 2 523456, 1 523456} 

As an alternative, using amalodic group-by code is as concise as possible.

+1
source

Source: https://habr.com/ru/post/1368986/


All Articles