Clojure получает наибольшее значение из zipmap

#clojure

#clojure

Вопрос:

Итак, у меня есть моя предлагаемая zip-карта, и она отлично работает. Как вы можете видеть, у меня есть загрузка данных.

Вот как это выглядит в repl, который является идеальным. И прямо здесь находится карта

 :Year 2020, :Day 27, :January 59, :February 38
:Year 2020, :Day 28, :January 41, :February 57
:Year 2020, :Day 29, :January 56, :February 51
:Year 2020, :Day 31, :January 94, :February -999
:Year 2020, :Day 30, :January 76, :February -999 

(map [:Day :Month
 

Имейте в виду, что это всего лишь фрагмент кода, который я сделал. Как бы вы предложили мне найти день с наибольшим значением в январе? И под наибольшим я подразумеваю число рядом с месяцами

 (into(sorted-map-by >(fn [:January]))Ha) 
 

Я безуспешно пытался это сделать, «Ha» в конце — это просто имя функции, в которой я инициализирую zipmap и использую io / reader для чтения файла

Комментарии:

1. Проще, если вы не используете zipmap . Возьмите cols 0,1,2, найдите max в col 2, затем извлеките day. Повторите для столбцов 0,1,3 (февраль). и т.д.

2. Есть ли причина, по которой zipmap сложнее?

Ответ №1:

Я бы использовал max-key и уменьшил:

 (def data [{:Year 2020, :Day 27, :January 59, :February 38}
           {:Year 2020, :Day 28, :January 41, :February 57}
           {:Year 2020, :Day 29, :January 56, :February 51}
           {:Year 2020, :Day 31, :January 94, :February -999}
           {:Year 2020, :Day 30, :January 76, :February -999}])

(reduce (partial max-key :January) data)
;; => {:Year 2020, :Day 31, :January 94, :February -999}

(:Day (reduce (partial max-key :January) data))
;; => 31
 

Комментарии:

1. Не могли бы вы дать мне небольшое объяснение относительно того, что делают обе функции, я не хочу брать на борт то, чего я не понимаю, хотя это очень хороший ответ 🙂

2. Обе функции довольно просты для понимания. Используйте ссылки в моем ответе, чтобы получить доступ к документации, прочитать, что они делают, и попробовать их самостоятельно в REPL. Я должен упомянуть, что reduce это очень практично для обработки последовательностей. По сути (reduce f [1 2 3 4]) , вычисляется (f (f (f 1 2) 3) 4) как .

3. Будет сделано, спасибо 🙂

4. Хороший вызов — я никогда max-key раньше не использовал. Хотя я бы выбрал apply вместо reduce .

5. @AlanThompson, вы правы: не нужно беспокоиться о сокращении частичном, когда вы можете просто сделать (apply max-key :January data)

Ответ №2:

Не уверен, как выглядит ваша точная структура данных, но, предполагая, что это вектор карт, вы можете сделать что-то вроде этого:

 (def data
  [{:Year 2020, :Day 27, :January 59, :February 38}
   {:Year 2020, :Day 28, :January 41, :February 57}
   {:Year 2020, :Day 29, :January 56, :February 51}
   {:Year 2020, :Day 31, :January 94, :February -999}
   {:Year 2020, :Day 30, :January 76, :February -999}])

(->> data
     (sort-by :January)
     last
     :January)
;; => 94
 

Сортировка вектора с помощью ключевого слова в качестве функции для поиска его значения на карте, затем взятие вектора с наибольшим значением за январь, затем получение значения, принадлежащего ключу :January , из этого вектора. Дайте мне знать, если ваша структура данных выглядит немного иначе.

Комментарии:

1. Да, моя структура данных точно такая, но в файле, из которого я ее загружаю, просто еще один быстрый вопрос: как бы вы также вернули год и день, с которого был получен самый высокий январь? Я пытался повысить ваш ответ, но моя учетная запись довольно новая, поэтому она не позволит мне :/

2. @Codemosh Вы можете выбрать несколько ключей, например juxt , применив к результату несколько функций (ключевых слов), которые вы хотите. Используя тот же max-key подход, что и выше ( apply max-key f в основном такой же, как ->> sort-by f last , возможно, только с немного лучшей производительностью), вы получаете ((juxt :Year :Day :January :February) (apply max-key :January m)) ;; => [2020 31 94 -999] .

3. @Codemosh Или вы можете использовать let привязку и деструктировать ключи следующим образом (let [{:keys [Year Day January February]} (apply max-key :January m)] [Year Day January February]) ;; => [2020 31 94 -999] .

Ответ №3:

ответ @Rule очень хороший. Без max-key этого было бы:

 (def data [{:Year 2020, :Day 27, :January 59, :February 38}
           {:Year 2020, :Day 28, :January 41, :February 57}
           {:Year 2020, :Day 29, :January 56, :February 51}
           {:Year 2020, :Day 31, :January 94, :February -999}
           {:Year 2020, :Day 30, :January 76, :February -999}])

(defn seq-max [seq greater key]
  (reduce (fn [a b] (if (greater (key a) (key b)) a b)) seq))
;; if no key is wanted, choose the function `identity` as key!
;; e.g.
;; (seq-max (map :January data) > identity)
;; => 94

(:Day (seq-max data > :January)) ;; => 31