我正在尝试以特定的方式对Clojure列表(或seq,如果它是所谓的)进行排序。我希望它按降序排列最后一项的优先级,然后按升序排列第一项。一个例子:
(def pnts '((1 2)
(2 4)
(3 2)
(4 10)
(5 3)
(6 1)
(7 2)))
(sort-by last > pnts)
;; ((4 10) (2 4) (5 3) (1 2) (3 2) (7 2) (6 1))
;; Notice how (1 2), (3 2), (7 2) are sorted. This
;; is correct and is what I want.
(排序最后)似乎正在做这个技巧,尽管这可能是因为这些点最初是按第一个项排序的。我正在实现我正在编写点的ASCII / CLI图形脚本的方式总是按照 pnts 的顺序排序。我的问题是什么是可以保证这样的排序首选项的命令?
PS我试过(排序方式(最后一个)(juxt><)pnts),但无济于事。
答案 0 :(得分:8)
我认为你使用juxt
走在正确的轨道上。假设您的积分都是数字,您可以撰写last
和-
来模拟最后一个组件的降序自然顺序。
user=> (sort-by (juxt (comp - last) first) (shuffle pnts))
((4 10) (2 4) (5 3) (1 2) (3 2) (7 2) (6 1))
答案 1 :(得分:5)
Sort使用Java的排序,这是稳定的,所以你也可以只排序两次
(def pnts (shuffle '((1 2) (2 4) (3 2) (4 10) (5 3) (6 1) (7 2))))
(->> pnts (sort-by first <) (sort-by last >))
;=> ((4 10) (2 4) (5 3) (1 2) (3 2) (7 2) (6 1))
答案 2 :(得分:3)
我已经改组输入以确保结果对于任意输入顺序是稳定的:
(sort #(or (> (last %1) (last %2))
(and (= (last %1) (last %2))
(< (first %1) (first %2))))
(shuffle '((1 2) (2 4) (3 2) (4 10) (5 3) (6 1) (7 2))))
=> ((4 10) (2 4) (5 3) (1 2) (3 2) (7 2) (6 1))
在这里我们验证,即使输入的1000次重新排序,输出只有一个排序:
(count (into #{}
(repeatedly
1000
(fn [] (sort #(or (> (last %1) (last %2))
(and (= (last %1) (last %2))
(< (first %1) (first %2))))
(shuffle '((1 2) (2 4) (3 2) (4 10) (5 3) (6 1) (7 2))))))))
=> 1
在这里,我们表明shuffle产生了大量的排序:
(count (into #{}
(repeatedly
1000
(fn [] (shuffle '((1 2) (2 4) (3 2) (4 10) (5 3) (6 1) (7 2)))))))
=> 899
(当然,由于shuffle是随机的,结果会有所不同,但计数似乎通常在850 - 950范围内)