简体   繁体   English

Clojure-使用最大值ArrayMap获取键

[英]Clojure - Get key with max value ArrayMap

I have a data set that looks like this: 我有一个数据集,看起来像这样:

({"1880" 5} {"1951" 6} {"1952" 5} {"1976" 10} {"1902" 7} {"1919" 7} {"1949" 12} {"1814" 4} {"1930" 11})

I am trying to get the key with the highest value. 我正在尝试获取具有最高价值的钥匙。 So in the case above I want to get the value "1949" back. 因此,在上述情况下,我想取回值"1949" I believe my answer lies with max-key , however I don't fully understand how max-key works. 我相信我的答案取决于max-key ,但是我不完全了解max-key工作原理。 For clarity as one answer was about looking at the string value: 为了清楚起见,一个答案是查看字符串值:

I want the string "1949" as the result because it has the highest number associated with it of 12 我想要字符串"1949"作为结果,因为它具有与之关联的最高数字12

Just use max-key , with a function to grab the val from each map: 只需使用max-key ,该函数具有从每个地图中获取val的功能:

(def data
  [{"1880" 5} {"1951" 6} {"1952" 5} {"1976" 10} {"1902" 7} {"1919" 7} {"1949" 12} {"1814" 4} {"1930" 11}])

(apply max-key #(val (first %)) data) => {"1949" 12}

You need the first function to convert each single element map into a MapEntry . 您需要第first函数将每个单个元素映射转换为MapEntry You can then use the val function to grab value out of the MapEntry: 然后,您可以使用val函数从MapEntry中获取值:

     (first {"1880" 5})    =>  <#clojure.lang.MapEntry ["1880" 5]>

(val (first {"1880" 5}))   =>  <#java.lang.Long 5>

Be sure to bookmark The Clojure CheatSheet and peruse it often! 请务必在Clojure CheatSheet上加上书签并经常仔细阅读!


PS Why first works for this: PS为什么first为此工作:

Note that you can convert a map into sequence of MapEntry's using either seq or vec : 请注意,您可以使用seqvec将地图转换为MapEntry的序列:

some-map               => <#clojure.lang.PersistentArrayMap {:a 1, :b 2}> 

(seq some-map)         => <#clojure.lang.PersistentArrayMap$Seq ([:a 1] [:b 2])>
(vec some-map)         => <#clojure.lang.PersistentVector [[:a 1] [:b 2]]>

You then need the first item from this seq/vector, which is where first comes in: 然后,您需要此seq / vector中的第一项,这是first

(first (vec some-map)) => <#clojure.lang.MapEntry [:a 1]>

Note, however, that first implicitly calls seq on whatever you pass to it, so we can skip the conversion and let first implicitly convert the map into a seq of MapEntry's for us: 但是请注意, first ,您对传递给它的任何内容都隐式调用seq ,因此我们可以跳过转换,而first让我们将地图隐式转换为MapEntry的seq:

(first some-map)  => <#clojure.lang.MapEntry [:a 1]>

You can sort your list of maps by the value of each map within it. 您可以按其中的每个地图的对地图列表进行排序。

(last (sort-by (comp second first) data))
=> {"1949" 12}

But looking at the data, I'm wondering it wouldn't just be a single map rather than a sequence of maps. 但是,查看数据,我想知道这将不仅仅是一张地图,而是一系列地图。 So I'm going to make the assumption that your data will never have duplicate keys, and then we can work with just a single map structure and it's easier: 因此,我将假设您的数据永远不会有重复的键,然后我们可以只使用一个地图结构,这会更容易:

(into {} data)
=> {"1919" 7, "1880" 5, "1814" 4, "1902" 7, "1951" 6, "1949" 12, "1976" 10, "1930" 11, "1952" 5}

Then you can get the same answer like this: 然后,您可以获得类似的答案:

(last (sort-by second (into {} data)))
=> ["1949" 12]

You can call first with these outputs to get just the string "1949" . 您可以first使用这些输出进行调用,以仅获取字符串"1949"

Here's another way to do it, sorting descending with a custom/reversed comparator: 这是另一种方式,使用自定义/反向比较器对降序进行排序:

(->> (into {} data)
     (sort-by second #(compare %2 %1))
     (ffirst))
 => "1949"

Since your keys aren't numbers (they are strings) you can't use max-key without casting to a number. 由于您的键不是数字(它们是字符串),因此您必须在不强制转换为数字的情况下使用max-key

You could achieve your desired result with this: 您可以通过以下方式实现所需的结果:

(last (sort (mapcat keys ({"1889" 1} {"1990" 2}))))

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM