2014-01-20 18 views
6

私はClojureリスト(またはそれが呼び出されている場合はseq)を特定の方法でソートしようとしています。最後の項目の優先順位を降順にソートし、次に最初の項目を昇順にソートします。例:Clojureのリストの並べ替え

(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最後に最初)(juxt> <)pnts)をやってみました。私は結果が任意の入力順のための安定していることを確認するために入力をシャッフルしている

答えて

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)) 
+0

私は_comp_も_juxt_も使い慣れていません - これはノードが最後に下降してから最初の昇順にソートするのでしょうか?あなたの例はそれをそのまま示していますが、私はそれが確実であることを望んでいます(この例題が何をしているのかわかりません)。 – user2958652

+0

他の質問では、騒音師は答えません。両方のおかげで、正直のためにnoisesmithに感謝:)私はさらに_juxt_と_comp_の両方を研究します。 – user2958652

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年reorderingsで、検証、出力の唯一の順序があります:

(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 

ここでは、シャッフルが順序の多種多様を生成することを示しています

(count (into #{} 
      (repeatedly 
       1000 
       (fn [] (shuffle '((1 2) (2 4) (3 2) (4 10) (5 3) (6 1) (7 2))))))) 
=> 899 

(シャッフルはランダム化されているので結果は変わりますが、カウントは通常850〜950の範囲内にあるようです)

+0

ああの素敵。 Clojure Docs http://clojuredocs.org/clojure_core/clojure.core/sort最初の/最後の項目にアクセスする必要がある場合は_sort-by_を使用することをお勧めします。私は、_sort-by_がキーワードn 'のマクロであると仮定します。 – user2958652

+1

以下のDaoWenの答えは実際にはこれをはるかにエレガントに解決しており、おそらくここで最善の答えとして受け入れられるはずです。 – noisesmith

+0

本当ですか?私はClojureの初心者です.DaoWenの答えはちょっとハッキリしていると思いました。彼の方法はちょうど速いでしょうか? – user2958652

5

ソートは安定している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)) 
関連する問題