2014-02-14 2 views
1

Я преподаватель университета, пытаясь получить удовольствие от Clojure и вычислить мои оценки в одно и то же время. Я сделал список всех моих студентов чисел с соответствующими сортов в то, что выглядит следующим образом:сопоставление каждого элемента в деструктурированном списке векторов в clojure

(def grades-1 (let [s18129 [100 70 85 71 85] 
        s18121 [80 75 85 81 85] 
        r18131 [75 60 80 56 75] ...]) 
        ;; r before the number is shorthand for repeater 
        ;; and not important to this question 

Я хотел бы ранги быть adusted так, что первый, второй, третий, четвертый и пятый классы в этих векторах взвешены до 10%, 20%, 15%, 25% и 30% соответственно. Для того, чтобы помочь мне решить эту задачу, я создал вспомогательную функцию:

(defn percentify 
    "adjust raw score to weighted percentile" 
    [raw percentile] 
    (* (/ raw 100) percentile)) 

Я хочу, чтобы создать другую функцию, которая будет отображать над списком классов и применить percentify функции сортов каждого студента на specfic веса для каждого элемента вектор, основанный на его положении. Это то, с чем я сейчас работаю, но я не могу заставить его работать в реплике. Я думаю, что это связано с тем, как я структурировал данные своего класса или, возможно, я смущен об использовании println.

(defn finalize [grades-list] 
(let [[[student] [a b c d e]] grades-list] 
    (println 
    (percentify a 10.0) 
    (percentify b 20.0) 
    (percentify c 15.0) 
    (percentify d 25.0) 
    (percentify e 30.0)))) 

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

ответ

1

Данные естественно карта от студента-номер (строка) к вектору оценок:

(def grades-1 {"s18129" [100 70 85 71 85] 
       "s18121" [80 75 85 81 85] 
       "r18131" [75 60 80 56 75]}) 

... и вектор весов, которые должны применяться к вышесказанному:

(def grade-weights [10 20 15 25 30]) 

... получив карту от ученика-номер до конечного класса. Как мы можем это учитывать?

функция для вычисления среднего по заданной weights вектора

(fn [grades] (/ (reduce + 0.0 (map * weights grades)) (reduce + weights))) 

... где

  • начальное значение 0.0 заставляет использовать с плавающей точкой арифметических и
  • вес не должен содержать до 1,0 или 100 или любое число в частности. Масштабирование включено.

Ниже преобразует каждое значение a-map в функцию f этого значения:

(fn [f a-map] (into {} (map (fn [[k v]] [k (f v)]) a-map))) 

Таким образом, функция, чтобы доставить карту окончательных оценок с карты векторов класса и весовой вектор является. ..

(defn av-grades [gt weights] 
    (let [weight-av (fn [grades] 
        (/ (reduce + 0.0 (map * weights grades)) (reduce + weights))) 
     convert-map (fn [f a-map] 
         (into {} (map (fn [[k v]] [k (f v)]) a-map)))] 
    (convert-map weight-av gt))) 

И, конечно же, ...

=>(av-grades grades-1 grade-weights) 
{"r18131" 68.0, "s18121" 81.5, "s18129" 80.0} 
+0

Спасибо, что потратили столько внимания на мою проблему. В итоге я решил упростить подход, основанный на ответе Майкла Марчика, но это действительно потрясающе и изначально то, что я просил. – kurofune

3

Во-первых, вы, кажется, назначаете вектор класса каждого ученика отдельному локальному в форме let. Чтобы отобразить функцию во всех векторах класса, вы должны поместить их в единой структуре данных первым:

(def grades-1 [[100 70 85 71 85] 
       [80 75 85 81 85] 
       [75 60 80 56 75]]) 

Теперь функция применить вектор весов к вектору класса будет полезно (percentify здесь ваша оригинальная функция):

;; taking weights first for convenient use with partial 
(defn percentify-vector [pvec rvec] 
    (mapv percentify rvec pvec)) 

Наконец, мы можем сопоставить выше по совокупности векторов класса:

(mapv (partial percentify-vector [10.0 20.0 15.0 25.0 30.0]) grades-1) 
+0

Это очень прибило его. Спасибо. Однако я пытаюсь уменьшить + каждый из расширенных векторов в одну последовательность окончательных оценок. Я сжимал это в функции и пытался назвать это, но, похоже, не мог заставить его работать. Не могли бы вы дать мне эту последнюю помощь? – kurofune

+0

Несомненно. Если я правильно понимаю, вы хотите суммировать каждый отдельный класс оценки и получить коллекцию всех итоговых сумм. Если «gs» ссылаться на коллекцию векторов классов с применяемыми весами, '(mapv # (apply +%) gs)' будет генерировать вектор сумм. Все это можно было бы сгустить до '(- >> grades-1 (map (partial percentify-vector [10.0 20.0 15.0 25.0 30.0])) (mapv # (apply +%)))'. –

+0

Боже мой, ты хорош в Кложуре. Надеюсь, когда-нибудь я смогу выкрикнуть такой код, как будто ничего. Спасибо. – kurofune

0

Я не могу улучшить ап Михала Marczyk в но я предложу возможную альтернативу. На данный момент это, вероятно, слишком велико для ваших потребностей. То, что вы хотите сделать, это по существу матричное умножение: вы умножаете матрицу на вектор, чтобы создать вектор. Это можно сделать напрямую, используя библиотеку core.matrix, если это необходимо. Предположим, что отдельные оценки предметов для викторины. Сначала вам нужно запустить Clojure с загруженной библиотекой core.matrix, например. используя Leiningen. Тогда в REPL или в файле, вы можете сделать это:

(use 'clojure.core.matrix) 

;; Define quiz grade matrix: Each row is a student, each column is a quiz. 
(def quiz-grades [[100 70 85 71 85] 
        [ 80 75 85 81 85] 
        [ 75 60 80 56 75]]) 

;; Define weights representing contributions of each quiz to the final grade. 
(def quiz-weights [0.10 0.20 0.15 0.25 0.30]) 

Здесь я определил веса для викторин как десятичных знаков, представляющих фракции 1, а не целые числа, но это легко преобразовать между двумя представлениями, используя map, mapv или аналогичная функция core.matrix, emap. Теперь вы можете получить окончательные оценки для каждого студента, как это:

user=> (mmul quiz-grades quiz-weights) 
[80.0 81.5 68.0] 

(Примечание: core.matrix имеет различные базовые реализации векторов и матриц В моем примере здесь, я использовал реализацию по умолчанию настойчивого-вектор, в. какие векторы и матрицы эквивалентны регулярным векторам Clojure и векторам векторов. Чтобы легко переключаться между различными реализациями, было бы лучше встроить векторы Clojure выше в вызовы функции matrix, но это необязательно с постоянным вектором реализация.)

+0

Спасибо, Марс. Это звучит потрясающе, и я полностью изучу библиотеку матриц. Я действительно новичок в Clojure и программировании, так что это здорово. Одна вещь, однако, окончательный расширенный вектор должен составлять число из 100%. Это их итоговый результат за семестр, каждый класс представляет собой домашнюю работу, презентации, эссе, средние и финальные, соответственно. Они находятся в том виде, в котором они из-за моего отсутствия предвидения в начале семестра. – kurofune

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

  • Нет связанных вопросов^_^