Robin
Robin

Reputation: 167

Reading key with greatest number from set

I have a set of maps as below

#{{:uid 2, :name "book2", :qty "2", :price "2"} {:uid 3, :name "book3", :price "1", :qty "1"}  
  {:uid 1, :name "book4", :qty "2", :price "2"}}

Now I want to read value of :uid with greatest number, so in this example I want to get 3.

Can anyone guide me how can I fetch this?

Upvotes: 1

Views: 44

Answers (4)

turingcomplete
turingcomplete

Reputation: 2188

You could try using reduce

(reduce #(max %1 (:uid %2)) 0 #{{:uid 2, :name "book2", :qty "2", :price "2"}
                                {:uid 3, :name "book3", :price "1", :qty "1"}}) 

Assuming the uids are non-negative.

EDIT:

It would be better to use a different starting value for the accumulator as recommended by @Thumbnail.

(reduce #(max %1 (:uid %2)) (Long/MIN_VALUE) #{{:uid 2, :name "book2", :qty "2", :price "2"}
                                               {:uid 3, :name "book3", :price "1", :qty "1"}}) 

This should work with negatives as well.

Upvotes: 0

Thumbnail
Thumbnail

Reputation: 13473

If you just want the number,

(defn max-uid [coll] (apply max (map :uid coll)))

will supply it.

(max-uid #{{:uid 2, :name "book2", :qty "2", :price "2"}
           {:uid 3, :name "book3", :price "1", :qty "1"}  
           {:uid 1, :name "book4", :qty "2", :price "2"}})

;3

Upvotes: 0

Arthur Ulfeldt
Arthur Ulfeldt

Reputation: 91534

The built in sorted-set-by function should do the trick:

user> (apply sorted-set-by  
     #(- (:uid %1) (:uid %2)) 
     #{{:uid 2, :name "book2", :qty "2", :price "2"} 
       {:uid 3, :name "book3", :price "1", :qty "1"}  
       {:uid 1, :name "book4", :qty "2", :price "2"}})
#{{:uid 1, :name "book4", :qty "2", :price "2"} 
  {:uid 2, :name "book2", :qty "2", :price "2"} 
  {:uid 3, :name "book3", :qty "1", :price "1"}}

then take the last one (or reverse the %1 and %2 comparator). Of course the usual trade-offs apply if for instance you where only going to get the value once and or it was a small set then a linear scan would be more efficient.

PS: I changed the data so all the uids are the same type

Upvotes: 2

RedDeckWins
RedDeckWins

Reputation: 2121

You could also use max-key

(:uid (apply max-key
        :uid
        #{{:uid 2, :name "book2", :qty "2", :price "2"} {:uid 3, :name "book3", :price "1", :qty "1"}
          {:uid 1, :name "book4", :qty "2", :price "2"}}))

This wouldn't work if the data was as given though, as the uids seem to be strings in some and numbers in other maps. Also, if the set was empty, this would fail.

Upvotes: 2

Related Questions