-
Notifications
You must be signed in to change notification settings - Fork 8
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Vadzimz homework 6 #22
base: main
Are you sure you want to change the base?
Changes from all commits
dc6a609
e06b680
e225a89
b0f435b
c4f2530
3a0cb24
df47508
370d245
7db6bbb
4d9e168
87105d3
20df132
51eb7a5
ecad7f6
aa186a8
cb49594
e99a55b
48cbfdb
6b44096
cafbdbc
a0fc441
c896d8e
9eb2b5f
8314db8
dba3c8a
6406b00
d260dbe
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,5 +1,5 @@ | ||
(ns otus.homework) | ||
|
||
|
||
(defn solution "Add your solution as fuction body here" []) | ||
(defn solution [] (double (/ (+ 5 4 (- 2 (- 3 (+ 6 (/ 4 5))))) (* 3 (- 6 2) (- 2 7))))) | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,6 +1,8 @@ | ||
(ns otus-02.homework.palindrome | ||
(:require [clojure.string :as string])) | ||
|
||
|
||
(defn is-palindrome [test-string]) | ||
(defn is-palindrome [test-string] | ||
(->> test-string string/lower-case | ||
(filter #(Character/isLetter %)) | ||
(#(= % (reverse %))))) | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,6 +1,10 @@ | ||
(ns otus-02.homework.pangram | ||
(:require [clojure.string :as string])) | ||
|
||
|
||
(defn is-pangram [test-string]) | ||
|
||
(defn is-pangram [test-string] | ||
(->> test-string string/lower-case | ||
(filter #(Character/isLetter %)) | ||
(map int) | ||
(into #{}) | ||
count | ||
(= 26))) |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,4 +1,7 @@ | ||
(ns otus-06.homework) | ||
(ns otus-06.homework | ||
(:require [clojure.string :as string]) | ||
(:require [clojure.java.io :as io]) | ||
(:require [clojure.set :as set])) | ||
|
||
;; Загрузить данные из трех файлов на диске. | ||
;; Эти данные сформируют вашу базу данных о продажах. | ||
|
@@ -94,3 +97,124 @@ | |
|
||
|
||
;; Файлы находятся в папке otus-06/resources/homework | ||
|
||
;; VARS | ||
;;************************************************** | ||
|
||
(def files (map #(str "homework/" %) ["cust.txt" "prod.txt" "sales.txt"])) | ||
|
||
;; запросы | ||
(def menu "\n*** Sales Menu *** | ||
------------------ | ||
1. Display Customer Table | ||
2. Display Product Table | ||
3. Display Sales Table | ||
4. Total Sales for Customer | ||
5. Total Count for Product | ||
6. Exit | ||
|
||
Enter an option\n") | ||
|
||
(def cust-req "Enter a customer name\n") | ||
(def item-req "Enter an item\n") | ||
|
||
;; ключи для чтения и отображения | ||
(def cust-keys [:custID :name :address :phoneNumber]) | ||
(def prod-keys [:prodID :itemDescription :unitCost]) | ||
(def sales-keys [:salesID :custID :prodID :itemCount]) | ||
(def sales-keys-to-show [:salesID :name :itemDescription :itemCount]) | ||
|
||
(def key-names [cust-keys prod-keys sales-keys]) | ||
|
||
;; ключи для конвертации и расчета total-sum | ||
(def keys-to-int [:itemCount :prodID :custID :salesID]) | ||
(def keys-to-double [:unitCost]) | ||
(def keys-to-count-total-sum [:unitCost :itemCount]) | ||
|
||
;; ключи для агрегации | ||
(def keys-to-cust-aggr [:name :totalCost]) | ||
(def keys-to-item-aggr [:itemDescription :itemCount]) | ||
|
||
;; FUNCTIONS | ||
;;********************************************************************** | ||
|
||
(defn read-to-maps | ||
"читаем файл с соответствующими keys в список мап" | ||
[f k] | ||
(let [r (io/reader (io/resource f))] | ||
(->> (line-seq r) | ||
(map #(string/split % #"\|")) | ||
(map #(zipmap k %))))) | ||
|
||
(defn update-mult-vals | ||
"преобразуем несколько столбов (keys), например, конвертируем" | ||
[map vals fun] | ||
(reduce #(update-in % [%2] fun) map vals)) | ||
|
||
(defn add-new-key | ||
"добавляем новый столбец (key), рассчитанный из нескольких существующих" | ||
[map keys name fun] | ||
(assoc map name (reduce fun (vals (select-keys map keys))))) | ||
|
||
(defn select-data | ||
"выделяем несколько столбцов и преобразуем каждую строку к виду мапа (ID - данные)" | ||
[keys-to-select key-to-first coll] | ||
(->> coll | ||
(map #(select-keys % keys-to-select)) | ||
(map #((fn [x key] (merge {(key x) (dissoc x key)})) % key-to-first)))) | ||
|
||
(defn aggregate | ||
"агрегируем данные aggr-key, группируя по name-key" | ||
[[name-key aggr-key] coll] | ||
(->> coll | ||
(map #(select-keys % [name-key aggr-key])) | ||
(group-by name-key) | ||
(map (fn [[name vals]] | ||
{name-key name | ||
aggr-key (reduce + (map aggr-key vals))})) | ||
(map #((fn [x key] {(key x) (dissoc x key)}) % name-key)) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Тоже лямбда в лямбде. Достаточно оставить |
||
(reduce merge))) | ||
|
||
(defn aggregate-and-filter | ||
"агрегируем и фильтруем результат по запрошенному значению name-key" | ||
[[name-key aggr-key] message coll] | ||
(println message) | ||
(flush) | ||
(let [filter-input (read-line)] | ||
(->> coll | ||
(aggregate [name-key aggr-key]) | ||
(#(find % filter-input))))) | ||
|
||
(defn print-result | ||
"печатаем либо результат, либо уточняющий запрос" | ||
[x] | ||
(if-not (nil? x) | ||
(run! println x) | ||
(println "Precise your input\n"))) | ||
|
||
|
||
;; собираем все данные в одну таблицу (список мап) | ||
(def full-data (->> (map #(read-to-maps %1 %2) files key-names) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Читать какие-либо файлы при инициализации namespace не стоит, так как это явный побочный эффект. А ведь модуль может быть потенциально использован как библиотека, а не только как самостоятельная программа - в этом случае безусловное чтение файлов будет мешать. А ещё подобные программы перечитывают файлы при каждом запросе от пользователя, ведь общение с последним происходит в диалоговом режиме, а в процессе диалога данные на диске могут и измениться. Кроме того не стоит обращаться к диску за теми данными, которые пользователю не нужны: как только попросит, тогда и следует нужные файлы читать. |
||
(reduce set/join) | ||
(map (fn [x] (update-mult-vals x keys-to-int #(Integer/parseInt %)))) | ||
(map (fn [x] (update-mult-vals x keys-to-double parse-double))) | ||
(map (fn [x] (add-new-key x keys-to-count-total-sum :totalCost *))))) | ||
|
||
(defn main | ||
"результирующая функция" | ||
[coll] | ||
(println menu) | ||
(flush) | ||
(let [x (read-line)] | ||
(println (str x "\n")) | ||
(->> (cond | ||
(= x "1") (select-data cust-keys :custID coll) | ||
(= x "2") (select-data prod-keys :prodID coll) | ||
(= x "3") (select-data sales-keys-to-show :salesID coll) | ||
(= x "4") (aggregate-and-filter keys-to-cust-aggr cust-req coll) | ||
(= x "5") (aggregate-and-filter keys-to-item-aggr item-req coll) | ||
(= x "6") ["Good Bye\n"]) | ||
Comment on lines
+210
to
+216
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Тут стоит case использовать вместо cond. |
||
print-result) | ||
(if (not= x "6") (main coll) nil))) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Здесь |
||
|
||
(main full-data) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Не стоит использовать имя "main" для именования функций, которые не являются точками входа в программу, то есть не принимают строго аргументы командной строки. Кроме того, производить какие-то побочные эффекты прямо в теле неймспейса - плохая практика. В данном случае следует объявить точку входа и настроить проект так, чтобы оная (точка входа) получала управление при выполнении команды |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Как-то сложновато выглядит. Зачем тут вложенные лямбды? Кажется, что стоит одну
(fn [x] ..)
оставить.