2012-09-30 3 views
5

가장 자주 나타나는 항목을 빈도가 내림차순으로 찾고 싶습니다. 그래서 예를 들어 나는이 단위 테스트가 통과하고 싶습니다 :관용구 Clojure 가장 가까운 항목을 연속으로 찾는 방법

(fact "can find 2 most common items in a sequence" 
     (most-frequent-n 2 ["a" "bb" "a" "x" "bb" "ccc" "dddd" "dddd" "bb" "dddd" "bb"]) 
     => 
     '("bb" "dddd")) 

나는 Clojure의에 여전히 표준 라이브러리와 그립에 도착하려고 매우 새로운 오전. 여기에 내가 무엇을 생각해 냈는가 :

(defn- sort-by-val [s]  (sort-by val s)) 
(defn- first-elements [pairs] (map #(get % 0) pairs)) 

(defn most-frequent-n [n items] 
    "return the most common n items, e.g. 
    (most-frequent-n 2 [:a :b :a :d :x :b :c :d :d :b :d :b]) => 
     => (:d :b)" 
    (take n (-> 
      items    ; [:a :b :a :d :x :b :c :d :d :b :d :b] 
      frequencies   ; {:a 2, :b 4, :d 4, :x 1, :c 1} 
      seq     ; ([:a 2] [:b 4] [:d 4] [:x 1] [:c 1]) 
      sort-by-val   ; ([:x 1] [:c 1] [:a 2] [:b 4] [:d 4]) 
      reverse    ; ([:d 4] [:b 4] [:a 2] [:c 1] [:x 1]) 
      first-elements))) ; (:d :b :a :c :x) 

그러나이 작업은 상당히 일반적인 작업을 수행하는 복잡한 체인처럼 보입니다. 이것을하기위한 더 우아하고 관용적 인 (또는보다 효율적인) 방법이 있습니까?

답변

8

일반적으로 정렬 기준과 빈도의 조합을 사용하여 빈도 정렬 목록을 얻습니다.

(sort-by val (frequencies ["a" "bb" "a" "x" "bb" "ccc" "dddd" "dddd" "bb" "dddd" "bb"])) 
=> (["x" 1] ["ccc" 1] ["a" 2] ["dddd" 3] ["bb" 4]) 

그러면 가장 낮은/가장 높은 빈도 항목을 쉽게 얻을 수 있습니다. 아마도 같은 : 다시 (떨어져 당신이 ->> 매크로의 영리한 사용과 도우미 기능을 필요로하지 않는다는 것을에서) 솔루션에 매우 유사하다

(defn most-frequent-n [n items] 
    (->> items 
    frequencies 
    (sort-by val) 
    reverse 
    (take n) 
    (map first))) 

.

전반적으로 나는 당신의 솔루션이 꽤 좋다고 생각합니다. 함수 체인에 대해 걱정하지 마십시오. 실제로 논리적으로 복잡한 개념 인 것은 매우 짧은 해결책입니다. C#/Java에서 똑같은 것을 코딩 해보면 내가 의미하는 것을 볼 수 있습니다 ......

+1

감사합니다. Mikera, 귀하의 솔루션은 개선되었습니다. (1) 도우미 함수의 필요성을 피하기 위해 화살표 매크로를 올바르게 사용하는 방법을 본다. (2)'sort-by '는'seq'를 먼저 할 필요없이'frequency'의 결과에 직접적으로 작용할 수 있습니다. (3) 표준 라이브러리에는'first' 함수가 있으므로 내 라이브러리를 만들 필요가 없습니다. (4)'map '이전에'take '를하는 것이 더 효율적입니다. –

+5

'(역순 (sort-by f coll))'은 진짜 이유가 없으므로 지독히 비쌉니다. 대신'(sort-by (comp-f) coll)'를 사용하십시오. 또한,'first'와'second' 또는'key'와'val'을 사용할 지에 대해서 일관성이 있습니다. 왜냐하면 그것들은 맵 엔트리와 동일하기 때문입니다. – amalloy

관련 문제