2011-08-25 88 views
4

我有地圖的載體,它看起來像這樣:獲取最大鍵的矢量地圖中的矢量

(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}]) 

我想借此最大:start時間爲每年:game。什麼是最好的方法來做到這一點?

回答

5

這裏又是另一種解決方案

user=> (map #(apply max-key :start %) 
      (vals (group-by :game game-vec))) 
({:game 1, :start 523456} 
{:game 2, :start 523456} 
{:game 3, :start 173456}) 
+0

我真的很喜歡多麼簡單本作的問題。這也是最不具破壞性的,因爲它可以保留任何其他可能存在的密鑰! – KushalP

2

一種方法是從矢量中獲得所有遊戲。

也許是這樣的:

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

現在,我們已經儲存了所有獨特的遊戲的地方,現在每個那些我們想要開始的最高值。如果我們篩選出正確的遊戲,排序可能會很有用。

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

所以我們可以得到我們想要的比賽,現在我們只需要其中最高

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

所以現在我們可以這樣做:

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

然而這僅僅是一個根據最佳定義,可能有更好的方法。

+0

(圖(FN [X](:從遊戲X)))是SMAE爲(圖:遊戲形式) – nickik

1

使用@nickik的最大函數思想對我的最後一個解決方案進行迭代。我相信有一個班輪在這裏的某個地方:-)

(reduce                                                          
(fn [m x]                                                         
    (assoc m (:game x)                                                      
      (max (:start x)                                                     
       (or (m (:game x)) 0))))                                                  
{} 
game-vec) 
2

我想出了這一點:

(defn max-start-per-game [coll] 
     (into {} (map (fn [[k v]] [k (apply max (map :start v))]) 
         (group-by :game game-vec)))) 

=> (max-start-per-game game-vec) 
{1 523456, 2 523456, 3 173456} 

的想法是讓在一個地方每場比賽的所有數據,然後取出開始的數據。然後就做一個最大的。

更一般的版本:

(defn collect [coll sum-key collect] 
    (into {} (map (fn [[k v]] [k (map :start v)]) 
       (group-by :game game-vec)))) 

(defn no-good-name 
    [coll f key1 key2] 
    (into {} (map (fn [[k v]] [k (f v)]) 
       (collect coll key1 key2))) 


(no-good-name game-veC#(apply max %) :game :start) 
=> {1 523456, 2 523456, 3 173456} 

(使用costum功能(稱爲FMAP中的contrib地方)到地圖的所有值映射過會probebly甚至更好,但你可以做你自己)

3
(into {} (for [[game times] (group-by :game game-vec)] 
      {game (apply max (map :start times))})) 
1

在功能上非常相似,朱利安Chastang的代碼,並使用reduce我:

(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}

或者使用group-by amalloy的代碼儘可能簡潔。