Clojure - 使用列表和日期时间

时间:2017-01-09 21:40:08

标签: list clojure jodatime

我完全陷入了这种情况。 我有一个代表银行交易的原子列表。

(#<Ref@29a71299: {:desc "DESC1", :amount 150, :date #<LocalDate 2017-01-10>}>)
(#<Ref@5a4ebf03: {:desc "DESC2", :amount 250, :date #<LocalDate 2017-01-10>}>)
(#<Ref@5a4ebf03: {:desc "DESC3", :amount -250, :date #<LocalDate 2017-01-11>}>)
(#<Ref@5a4ebf03: {:desc "DESC4", :amount 50, :date #<LocalDate 2017-01-12>}>)

我需要在当天结束时计算余额账户,因此我应该抓住每天分开的所有交易以了解当天结束时的余额。

之前有人做过吗?过滤日期并进行数学计算的最佳方法是什么?我仍然是残疾人/学生。

OBS。我正在使用此库来处理日期Jodatime

3 个答案:

答案 0 :(得分:1)

解决Clojure问题的一个好方法是思考:

  1. 如何解决这个问题(这通常是困难的部分)
  2. 我如何单独解决每个问题
  3. 如何撰写这些解决方案(这通常很容易)
  4. 将此问题应用于您的问题我发现了以下问题:

    • 按其中一个键的属性

      分割地图列表

      (partition-by ... something ...)

    • 对每个地图序列中的一个键的所有值求和

      (map (reduce ...))

    • 使用数据和每个段的总和制作输出格式

      (map ... something)

    组成部分可能只是将每个嵌套作为嵌套函数调用嵌套。嵌套函数调用可以使用thread-last maco编写,看起来像这样:

    (->> data
        (... problem one solution ...)
        (problem two solution)
        (some output formatting for problem three))
    

答案 1 :(得分:0)

这最终变得比我想象的要复杂得多。我看了partition-by,你几乎肯定会使用它。它非常适合这个问题。这只是一个如何使用loop

完成的示例
(defn split-dates [rows]
  (loop [[row & rest-rows] rows ; Split on the head
         last-date nil
         acc [[]]]
    (if row
      (let [current-date (last row)]
        (recur rest-rows current-date
          ; If the day is the same as the previous row
          (if (or (nil? last-date) (= current-date last-date))
            ; Update the current day list with the new row
            (update acc (dec (count acc))
                    #(conj % row))
            ; Else, create a new list of rows for the new date
            (conj acc [row]))))
      acc)))
(clojure.pprint/pprint
  (split-dates
    [[0 1 "16.12.25"]
     [2 3 "16.12.25"]
     [4 5 "16.12.26"]
     [6 7 "16.12.26"]
     [8 9 "16.12.26"]
     [1 9 "16.12.27"]]))

[[[0 1 "16.12.25"] [2 3 "16.12.25"]]
 [[4 5 "16.12.26"] [6 7 "16.12.26"] [8 9 "16.12.26"]]
 [[1 9 "16.12.27"]]]

注意:

  • 这假设日期在最后一列,并且行按日期排序。

  • 给定空列表时返回[[]]。这可能是您想要的也可能不是。

答案 2 :(得分:0)

您可能希望以这种方式将其分解:

(defn per-day-balance [txns]
  (->> txns
       (partition-by :date)
       (map (fn [[{date :date} :as txns]]
              {:date date :balance (reduce + (map :amt txns))}))))

假设每天从0开始,找出每日余额。样本运行:

(def txns [{:date 1 :amt 10}
           {:date 1 :amt 3}
           {:date 2 :amt 9}
           {:date 2 :amt -11}
           {:date 3 :amt 13}])

user> (per-day-balance txns)
=> ({:date 1, :balance 13} {:date 2, :balance -2} {:date 3, :balance 13})

现在添加减少功能以获得运行总计。缩减功能只是简单地更新&#39;累积余额:

(defn running-balance [bals]
  (let [[day-1 & others] bals]
    (reductions
     (fn [{running :balance} e] (update e :balance + running))
     day-1
     others)))

示例运行:

user> (->> txns
           per-day-balance
           running-balance)
=> ({:date 1, :balance 13} {:date 2, :balance 11} {:date 3, :balance 24})

注意:您可以使用以下任何数据类型:日期字段。其次,我故意避免使用atom来使函数变得纯净。