2013-10-07 6 views
1

Я пытаюсь извлечь максимальные и минимальные результаты из SQL-запроса в Clojure, чтобы я мог выполнять математический анализ, но я не уверен, почему я получаю сообщение об ошибке.Получение значений max и min в Clojure

Я использовал функции max и min в коде, чтобы попытаться определить эти результаты, хотя я все время возвращаю две ошибки, которые, как представляется, относятся к тому, как я использую ключевое слово : counter.

Данные, возвращаемые в карте из запроса SQL выглядит следующим образом:

{:date1 "20131007", :data "object1", :counter 1000} 
    {:date1 "20131007", :data "object2", :counter 50} 
    {:date1 "20131007", :data "object3", :counter 230} 

Когда я использую этот код:

minvalue(min(map(keyword :counter)data2)) 
    maxvalue(max(map(keyword :counter)data2)) 
    valrange(- maxvalue minvalue) 
    valpc(* (/ valrange 100) 10) 
    x(- maxvalue valpc) 

Я бы, очевидно, хотят MinValue быть установлен как 50 и maxvalue будет установлен в 1000, хотя я получаю эту ошибку:

java.lang.ClassCastException: clojure.lang.LazySeq cannot be cast to java.lang.Number 

Если удалить функцию карты из кода и запустить его снова, я получаю эту ошибку:

java.lang.ClassCastException: clojure.lang.Keyword cannot be cast to java.lang.Number 

любая помощь по этому вопросу, как я полностью застрял (и, вероятно, довольно ovbious, что я м новичок в Clojure)! Благодаря

+1

обратите внимание на производительность: если у вас есть большее количество карт для обработки, используйте сокращение (что-то вроде '(уменьшить min (: counter (first maps)) (map: counter (rest maps)))) будет более эффективным, чем применимо. – noisesmith

ответ

6

Несколько изменений из кода:

  • мин и макс принимать переменное число параметров, а не коллекцию. Используйте это применимо, а затем примените содержимое коллекции как параметры.
  • конвенции Clojure именование использование - между словами
  • Допустимых вызовов должны быть в форме (в основном списке, где первый элемент является вызываемым)
  • Нет необходимости использовать «ключевое слово», ключевое слово, когда у вас есть string и нужно связанное ключевое слово. Для перетаскивания данных из карты ключевых слов действуют как сами функции например (: а {: 1: 2 б}) возвращает 1.
  • факторизовали общность в первые две строки

    (def data [{:date1 "20131007", :data "object1", :counter 1000} 
          {:date1 "20131007", :data "object2", :counter 50} 
          {:date1 "20131007", :data "object3", :counter 230}]) 
    
    (def counters (map :counter data))  ; => (100 50 230) 
    (def min-value (apply min counters)) ; => 50 
    (def max-value (apply max counters)) ; => 1000 
    (def val-range (- max-value min-value)) ; => 950 
    (def val-pc (* (/ val-range 100) 10)) ; => 95 
    (def x (- max-value val-pc))   ; => 905 
    
3
user=> data 
[{:data "object1", :date1 "20131007", :counter 1000} {:data "object2", :date1 "20131007", :counter 50} {:data "object3", :date1 "20131007", :counter 230}] 

user=> (apply max-key :counter data) 
{:data "object1", :date1 "20131007", :counter 1000} 

user=> (apply min-key :counter data) 
{:data "object2", :date1 "20131007", :counter 50} 
+0

Спасибо, я только что пробовал код выше, и я все еще получаю сообщение об ошибке: java.lang.ClassCastException: clojure.lang.LazySeq нельзя отнести к java.lang.Number. Я ищу только фактическое целочисленное значение из: счетчика, который нужно вернуть, чтобы я мог работать с фактическим значением. В очередной раз благодарим за помощь! – Paul

+1

Если вы хотите использовать только значение '(применить min (map: counter data))' или '(уменьшить min (map: counter data))'. Код выше и этот код работает. 'data' должен быть вектором карт. – defhlt

Смежные вопросы