在 Clojure 中使用 for 更新地图值
Updating values of map using for in Clojure
我有一个如下所示的 json 并且需要在其中添加值
{ "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"
}
]
}
在上面的地图中,我需要在每个地图类别的最后一个值中添加一个字段“message”。因此,在添加值后,我期望生成的地图如下所示
{ "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"
}
]
}
我试过用下面的方法实现它
(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")}))
我希望通过执行函数得到的结果输出是一个如下所示的向量
[
{
"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"
}
]
并且由于没有返回任何值,所以我得到 null 作为输出。有人可以帮忙解决这个问题吗?
这是一个有效的例子。一、声明&数据:
(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' } ] }"))
然后处理:
(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)))]
验证结果:
(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"}]]]
)))
请参阅文档列表 in this template project,尤其是 Clojure CheatSheet。
我有一个如下所示的 json 并且需要在其中添加值
{ "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"
}
]
}
在上面的地图中,我需要在每个地图类别的最后一个值中添加一个字段“message”。因此,在添加值后,我期望生成的地图如下所示
{ "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"
}
]
}
我试过用下面的方法实现它
(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")}))
我希望通过执行函数得到的结果输出是一个如下所示的向量
[
{
"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"
}
]
并且由于没有返回任何值,所以我得到 null 作为输出。有人可以帮忙解决这个问题吗?
这是一个有效的例子。一、声明&数据:
(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' } ] }"))
然后处理:
(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)))]
验证结果:
(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"}]]]
)))
请参阅文档列表 in this template project,尤其是 Clojure CheatSheet。