如何在嵌套映射中使用sort-by,当键是字符串而不是关键字时?

huangapple go评论81阅读模式
英文:

How do I use sort-by on nested maps when the keys are strings, not keywords?

问题

This works with keywords

(sort-by (comp :rank second) > 
  {:1 {:bar "something" :rank 10} :2 {:bar "other" :rank 20}})

This fails when it's a string

(sort-by (comp "rank" second) >
  {:1 {:bar "something" "rank" 10} :2 {:bar "other" "rank" 20}})

Error message is "Execution error (ClassCastException) at java.util.TimSort/countRunAndMakeAscending (TimSort.java:355).
java.lang.String incompatible with clojure.lang.IFn"

I take it the problem is that keywords can be a function but strings cannot be functions. What is the solution? I've tried playing around with get without success.

英文:

Related question.

This works with keywords

(sort-by (comp :rank second) > 
  {:1 {:bar "something" :rank 10} :2 {:bar "other" :rank 20}})

This fails when it's a string

(sort-by (comp "rank" second) >
  {:1 {:bar "something" "rank" 10} :2 {:bar "other" "rank" 20}})

Error message is "Execution error (ClassCastException) at java.util.TimSort/countRunAndMakeAscending (TimSort.java:355).
java.lang.String incompatible with clojure.lang.IFn"

I take it the problem is that keywords can be a function but strings cannot be functions. What is the solution? I've tried playing around with get without success.

答案1

得分: 2

comp 组合函数,所以您需要一个可以通过字符串获取键的函数:

user> (->> {:1 {:bar "something" "rank" 10} :2 {:bar "other" "rank" 20}}
           (sort-by (comp #(get % "rank") second) >))
([:2 {:bar "other", "rank" 20}] [:1 {:bar "something", "rank" 10}])
英文:

comp composes functions, so you'll need a function that can get the key by string:

user> (->> {:1 {:bar "something" "rank" 10} :2 {:bar "other" "rank" 20}}
           (sort-by (comp #(get % "rank") second) >))
([:2 {:bar "other", "rank" 20}] [:1 {:bar "something", "rank" 10}])

答案2

得分: 1

(comp :rank second) 表达的意思与 (fn [x] (:rank (second x))) 写法相同。

类似地,(comp :rank "second") 会变成 (fn [x] (:rank ("second" x))),但是 "second" 是一个字符串,不能像函数一样调用。

可以使用一个函数替代,比如 #(get % "second") 或者只是 #(% "second")

英文:

The expression (comp :rank second) is the same as writing (fn [x] (:rank (second x))).

Similarly, (comp :rank "second") would be (fn [x] (:rank ("second" x))), but "second" is a String. It cannot be invoked like a function.

Use a function instead, like #(get % "second") or just #(% "second").

答案3

得分: 0

In Clojure, a keyword can act as a function, so it works with comp. A String does not have this special status. The easiest way is to make a dedicated function to extract the sort key. Here is one way with unit tests:

(ns tst.demo.core
  (:use tupelo.core tupelo.test))

(defn nested-rank
  [me]
  (get (second me) "rank"))

(verify
  ; when iterating over a map, each map-entry looks like a 2-elem vector
  (is= 10 (nested-rank [:1 {:bar "something" "rank" 10}]))

  (let [data {:1 {:bar "something" "rank" 10}
              :2 {:bar "other" "rank" 20}}]
    (is= (sort-by nested-rank > data)
      [[:2 {:bar "other" "rank" 20}]
       [:1 {:bar "something" "rank" 10}]])))

Build using my favorite template project.

英文:

In Clojure, a keyword can act as a function, so it works with comp. A String does not have this special status. The easiest way is to make a dedicated function to extract the sort key. Here is one way with unit tests:

(ns tst.demo.core
  (:use tupelo.core tupelo.test))

(defn nested-rank
  [me]
  (get (second me) "rank"))

(verify
  ; when iterating over a map, each map-entry looks like a 2-elem vector
  (is= 10 (nested-rank [:1 {:bar "something" "rank" 10}]))

  (let [data {:1 {:bar "something" "rank" 10}
              :2 {:bar "other" "rank" 20}}]
    (is= (sort-by nested-rank > data)
      [[:2 {:bar "other" "rank" 20}]
       [:1 {:bar "something" "rank" 10}]])))

build using my favorite template project.

huangapple
  • 本文由 发表于 2023年5月10日 23:59:03
  • 转载请务必保留本文链接:https://go.coder-hub.com/76220511.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定