简体   繁体   中英

Updating values of map using for in Clojure

I have a json like below and have a requirement to add values in it

{ "10 days refund": [
        {
            "paymentType": "CreditCard",
            "amount": "40$",
            "expiryDate": "20/10/2025"
        },
        {
            "paymentType": "CreditCard",
            "amount": "20$",
            "expiryDate": "20/1/2024"
        }
    ],
    "3 hours refund": [
        {
            "paymentType": "DebitCard",
            "amount": "10$",
            "expiryDate": "20/10/2026"
        },
        {
            "paymentType": "DebitCard",
            "amount": "5$",
            "expiryDate": "20/10/2027"
        }
    ]
}

In the above map, I would need to add a field "message" to last value of each category of map. So after adding the value I'm expecting the resultant map like below

{ "10 days refund": [
            {
                "paymentType": "CreditCard",
                "amount": "40$",
                "expiryDate": "20/10/2025"
            },
            {
                "paymentType": "CreditCard",
                "amount": "20$",
                "expiryDate": "20/1/2024",
                "message" : "Refund will be processed in 10 days"
            }
        ],
        "3 hours refund": [
            {
                "paymentType": "DebitCard",
                "amount": "10$",
                "expiryDate": "20/10/2026"
            },
            {
                "paymentType": "DebitCard",
                "amount": "5$",
                "expiryDate": "20/10/2027",
                "message" : "Refund will be processed in 3 hours"
            }
        ]
    }

I have tried implementing it using below method

(defn ^:private payment-methods
  [pm-sorted]
  (let [categories (group-by pm-fingerprint pm-sorted)]
    (for [[pm-fingerprint pm-sorted] categories
          :let [last-payment-method (last pm-sorted)
                dropped-last (drop-last pm-sorted)]]
      (if (= (:refund-category pm-fingerprint) "10 hours refund")
        ((println "10 days refund")
         (doall (conj (doall dropped-last) (assoc last-payment-method :message
                                                                      (text (str "Refund will be processed in 10 days"))))))
        ((println "3 hours refund")
         (doall (conj (doall dropped-last) (assoc last-payment-method :message
                                                                      (text (str "Refund will be processed in 3 hours"))))))))))

(defn ^:private pm-fingerprint
  [payment-method]
  (let [payment-type ("paymentType" payment-method)]
    {:refund-category (if (= payment-type "CreditCard"))
                     "10 days refund"
                     "3 hours refund")}))

I expect the resultant output by executing the function to be a vector like below

[
{
                    "paymentType": "CreditCard",
                    "amount": "40$",
                    "expiryDate": "20/10/2025"
                },
                {
                    "paymentType": "CreditCard",
                    "amount": "20$",
                    "expiryDate": "20/1/2024",
                    "message" : "Refund will be processed in 10 days"
                }
                {
                    "paymentType": "DebitCard",
                    "amount": "10$",
                    "expiryDate": "20/10/2026"
                },
                {
                    "paymentType": "DebitCard",
                    "amount": "5$",
                    "expiryDate": "20/10/2027",
                    "message" : "Refund will be processed in 3 hours"
                }
            ]

And I get null as the output as no value is returned. Can someone please help wrt the issue?

Here is an example that works. First, declarations & data:

(ns tst.demo.core
  (:use tupelo.core tupelo.test)
  (:require
    [schema.core :as s]
    [tupelo.string :as str]
  ))

(def input
  (str/quotes->double
    "{ '10-days-refund': [
            { 'paymentType': 'CreditCard',
                'amount': '40$',
                'expiryDate': '20/10/2025' },
            { 'paymentType': 'CreditCard',
                'amount': '20$',
                'expiryDate': '20/1/2024' }
        ],
        '3-hours-refund': [
            {
                'paymentType': 'DebitCard',
                'amount': '10$',
                'expiryDate': '20/10/2026' },
            { 'paymentType': 'DebitCard',
                'amount': '5$',
                'expiryDate': '20/10/2027' } ] }"))

Then the processing:

(dotest
  (let [data  (json->edn input)
        data2 (vec
                (for [entry data]
                  (let [[the-key pmt-lst] entry ; destruture into key and list of vals
                        pmt-lst-butlast   (butlast pmt-lst)
                        pmt-lst-last      (last pmt-lst)
                        last-new          (assoc pmt-lst-last :message "Coming Soon!")
                        pmt-lst-new       (append pmt-lst-butlast last-new)
                        entry-new         [the-key pmt-lst-new]]
                    entry-new)))]

and the result verified:

    (is= data2
         [[:10-days-refund
           [{:amount "40$" :expiryDate "20/10/2025" :paymentType "CreditCard"}
            {:amount      "20$"
             :expiryDate  "20/1/2024"
             :message     "Coming Soon!"
             :paymentType "CreditCard"}]]
          [:3-hours-refund
           [{:amount "10$" :expiryDate "20/10/2026" :paymentType "DebitCard"}
            {:amount      "5$"
             :expiryDate  "20/10/2027"
             :message     "Coming Soon!"
             :paymentType "DebitCard"}]]]
    )))

Please see the list of documentation in this template project , especially the Clojure CheatSheet.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM