Преимущество языка, в котором упор делается на интерактивное программирование в REPL, заключается в том, что вы можете очень легко экспериментировать со всеми маленькими частями, из которых состоит ваша функция.
Сначала определите list
как ваши данные.
(def list '((a b c) (d e) (f g h) (d e) (i j k l) (m n) (o)))
Затем оцените формы в вашей функции lfsort
(единственный аргумент которой удобно называть list
). Начните с оценки самых внутренних форм, а затем постепенно расширяйтесь, пока не оцените все тело функции. Используйте doc
для всех встроенных функций и экспериментируйте!
So:
(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)]}
… теперь у нас есть карта подсчетов в списки размера «подсчет»…
(vals (group-by count list))
; => ([(a b c) (f g h)] [(d e) (d e) (m n)] [(i j k l)] [(o)])
… теперь у нас есть последовательность только значений карты (каждый из векторов значений содержит списки одинакового размера)…
(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))
… наконец, списки распаковываются из векторов и сглаживаются в простую последовательность. Списки в последовательности теперь упорядочены, причем те списки, размеры которых встречаются реже всего, находятся впереди.
Между прочим, последнюю операцию mapcat
можно было бы выразить проще с помощью (apply concat ,,,)
.
07.01.2017