【问题标题】:Sorting a vector of maps by a value in map against a vector of those values - Clojure根据这些值的向量,按地图中的值对地图向量进行排序 - Clojure
【发布时间】:2021-02-01 21:46:25
【问题描述】:

我们在 clojure 中有 sort-by 可以根据向量或映射对值进行排序。

例如,如果我有一个要排序的向量:

(def ^:const sort-numbers ["one" "two" "three" "four" "five"])

我有这个带有无序值的随机向量,例如:

(def numbers ["two" "three" "one" "four"])

现在,它们可以按以下方式排序:

(sort-by #(.indexOf sort-numbers %) numbers)

再次,现在我有了这个地图矢量:

(def numbers-map [{:one 1 :two 2 :three 3} 
                  {:one 4 :two 4 :three 3}
                  {:one 3 :two 2 :three 1}])

如果我想通过键 :one 的值对向量中的所有映射对 numbers-map 进行排序,

(sort-by :one numbers-map)

会,它会给我以下结果:

({:one 1, :two 2, :three 3} {:one 3, :two 2, :three 1} {:one 4, :two 4, :three 3})

现在,我需要的是这些的组合。 也就是说,我需要通过键:one 的值对numbers-map 进行排序,但我不希望它们自动排序,而是根据:one 的所有可能值的指定向量对它们进行排序我已经在某个地方了。

如何实现?

【问题讨论】:

  • 您能否向我们展示您在某处拥有的所有可能的 :one 值的指定向量?以及给定输入的预期输出?
  • @jas 让我们使用任意向量,例如:(def ^:const one-values [10 5 1 2 4 3]。因此,与其以增量方式自动排序,不如根据向量one-values 中这些值的索引来进行。
  • @jas 根据向量排序得到的预期输出是:({:one 1, :two 2, :three 3}, {:one 4, :two 4, :three 3}, {:one 3 :two 2 :three 1}) 注意143出现在向量one-values中的顺序.
  • 不要使用^:const 只是因为你不希望值改变。这是 Clojure 中 all 值的期望,因此 ^:const 表示其他含义。对于编译器来说,它基本上意味着“我鼓励你每次使用这个值时都内联它”,这是你很少想做的事情。

标签: clojure


【解决方案1】:

这让你可以这样做

(def numbers-maps [{:one 1 :two 2 :three 3} 
                   {:one 4 :two 4 :three 3}
                   {:one 3 :two 2 :three 1}])

(def sort-numbers [4 3 2 1])

(sort-by #(.indexOf sort-numbers (:one %))
         numbers-maps)

({:one 4, :two 4, :three 3}
 {:one 3, :two 2, :three 1}
 {:one 1, :two 2, :three 3})

这是另一个例子:

(def numbers-maps [{:one 6, :two 9, :three 9}
                   {:one 9, :two 9, :three 8}
                   {:one 7, :two 6, :three 2}
                   {:one 4, :two 4, :three 5}
                   {:one 9, :two 1, :three 5}
                   {:one 1, :two 8, :three 8}
                   {:one 8, :two 3, :three 9}
                   {:one 8, :two 4, :three 5}
                   {:one 4, :two 8, :three 1}
                   {:one 5, :two 1, :three 1}])

(def one-values [10 5 1 2 4 3])

(sort-by #(.indexOf one-values (:one %))
         numbers-maps)

({:one 6, :two 9, :three 9}
 {:one 9, :two 9, :three 8}
 {:one 7, :two 6, :three 2}
 {:one 9, :two 1, :three 5}
 {:one 8, :two 3, :three 9}
 {:one 8, :two 4, :three 5}
 {:one 5, :two 1, :three 1}
 {:one 1, :two 8, :three 8}
 {:one 4, :two 4, :three 5}
 {:one 4, :two 8, :three 1})

【讨论】:

  • 谢谢。我认为应该这样做,但不知何故错过了这种形式。 :D
  • 效率提示 - indexOf 对向量进行线性扫描,因此如果向量很大并且您经常查找第 1000 个元素的索引,这可能会很慢。在某些情况下,从值到它们的相对索引预先计算 Clojure 映射可能会更快,即它为您要传递给 #(.indexOf one-values my-val) 的每个可能值提供 my-val 作为键,索引值作为关联值,因此可以比线性扫描更快地确定它。
猜你喜欢
  • 2018-01-08
  • 1970-01-01
  • 1970-01-01
  • 2015-11-07
  • 2013-08-27
  • 1970-01-01
  • 2012-04-25
  • 2017-09-14
  • 1970-01-01
相关资源
最近更新 更多