Как объединить пары на основе вложенного значения? - PullRequest
1 голос
/ 25 октября 2019

Учитывая следующий список в Clojure:

(def pairs '[(2,1),(3,2),(2,4)])

Я хочу объединить эти основанные на перекрытии первый элемент в паре и выбрать один с большим вторым значением.

т.е. хотите, чтобы они слились в:

[(3,2),(2,4)]   

, потому что (2,1) и (2,4) имеют совпадающие первые значения, а (2,4) имеет большее второе значение, поэтому он отбрасывает (2,1).

Мой вопрос: Как объединить пары на основе вложенного значения?

Это то, что я пытался:

(reduce
  (fn [first-pair second-pair]
    (if (not (= (first first-pair) (first second-pair)))
      (conj first-pair second-pair)
      (if (> (second first-pair) (second second-pair))
        first-pair
        second-pair)))
  pairs
  )

Ответы [ 2 ]

4 голосов
/ 25 октября 2019

самое простое - сначала сгруппировать все, а затем найти максимум в каждой группе:

user> (->> pairs
           (group-by first)
           vals
           (map (fn [data] (apply max-key second data))))
;;=> ((2 4) (3 2))

также вы можете сделать это за один проход, без промежуточных последовательностей:

user> (seq (reduce (fn [acc [f s]]
                     (update acc f (fnil max Double/NEGATIVE_INFINITY) s))
                   {} pairs))
;;=> ([2 4] [3 2])
2 голосов
/ 25 октября 2019

Если вы не возражаете против промежуточного сбора, вы можете сгруппировать по first и по максимуму для каждой группы. Например,

user=> (map (partial apply max-key second) (vals (group-by first pairs)))
((2 4) (3 2))
...