在Clojure中根据它们的长度频率对此列表的元素进行排序

时间:2017-01-07 15:07:29

标签: clojure

all

今天在研讨会上,我们正在讨论上述功能,如果给出,(defn lfsort [list](mapcat #(if (sequential? %) % [%]) (sort-by count (vals (group-by count list))))) 输出:

(lfsort '((a b c) (d e) (f g h) (d e) (i j k l) (m n) (o)))

我们开始编写一个函数,使用

按长度顺序对其进行排序
((i j k l)
 (o)
 (a b c)
 (f g h)
 (d e)
 (d e)
 (m n))

输出:

(defn sort [list] (sort-by count list))

我理解排序功能是如何工作的,但我仍然不确定lfsort是如何做的,有人可以帮助我愚蠢吗?

谢谢!

2 个答案:

答案 0 :(得分:1)

一种强调REPL交互式编程的语言的优点在于,您可以非常轻松地尝试构成您功能的所有小部分。

首先将list定义为您的数据。

(def list '((a b c) (d e) (f g h) (d e) (i j k l) (m n) (o)))

然后评估lfsort函数中的表单(唯一的参数是方便地命名为list)。首先评估最里面的形式,然后逐渐扩展,直到您评估整个函数体。在所有内置函数上使用doc,然后进行实验!

所以:

(group-by count list)
; => {3 [(a b c) (f g h)], 2 [(d e) (d e) (m n)], 4 [(i j k l)], 1 [(o)]}

...现在我们有一个计数大小'count'列表的地图......

(vals (group-by count list))
; => ([(a b c) (f g h)] [(d e) (d e) (m n)] [(i j k l)] [(o)])

...现在我们只有map的值(每个值向量包含相同大小的列表)...

(sort-by count (vals (group-by count list)))
; => ([(i j k l)] [(o)] [(a b c) (f g h)] [(d e) (d e) (m n)])

...现在seq中的向量按其中有多少列表排序......

(mapcat #(if (sequential? %) % [%])
  (sort-by count (vals (group-by count list))))
;; => ((i j k l) (o) (a b c) (f g h) (d e) (d e) (m n))

...最后,列表从向量中解压缩并展平成一个简单的seq。现在订购了seq中的列表,其中列表的大小在前面的频率最低。

顺便说一下,mapcat可以更简单地表达(apply concat ,,,)操作。

答案 1 :(得分:1)

首先,我们可以简化为

(defn lfsort [coll]
  (apply concat 
   (sort-by count (vals (group-by count coll)))))

...因为sequential?始终返回true

我们可以将其重新声明为

(defn lfsort [coll]
  (->> coll
       (group-by count)
       vals
       (sort-by count)
       (apply concat)))

...使用->>线程最后一个宏。

所以这个功能

  • 采用其参数coll
  • count
  • 对其集合元素进行分组
  • 丢弃密钥,映射到矢量值,
  • 按长度对这些向量进行排序,最后
  • 连接矢量。
相关问题