![](/img/trans.png)
[英]How do I return a clojure map with fixed keys and conditional values?
[英]How do I conditionally update keys and values in a Clojure map based on the key name?
我有一個 map,鍵是字符串。 如果密鑰包含單詞“kg”,我想將該值乘以 2.2,然后將密鑰中的“kg”替換為“lb”。 我不知道如何以可以有條件地更新它的方式迭代 map。
示例 map:
{"id" ("7215" "74777" "7219"),
"weight-kg" ("150" "220" "530"),
"time-seconds" ("1900" "2" "770")}
所需 output
{"id" ("7215" "74777" "7219"),
"weight-lb" ("330" "485" "1168"),
"time-seconds" ("1900" "2" "770")}
我試過update
for
map
和reduce-kv
。 項目需求是不使用字符串庫,所以才會有re-find
。 這些只是改變價值觀的嘗試。 由於我無法更改值,因此我沒有嘗試更改密鑰。
(defn kg->lb [m k]
(if (re-find #"kg" k)
(map #(update m % * 2.2))))
(defn kg2->lb2 [m]
(reduce-kv #(if (re-find #"kg" %)
(update % * 2.2)) {} m)
(map #(if (re-find #"kg" %)
(update % * 2.2)) m)
(for [k (keys m)]
(if (re-find #"kg" k)
(update m k #(* % 2.2))))
數據:
(def data {"id" ["7215" "74777" "7219"],
"weight-kg" ["150" "220" "530"],
"time-seconds" ["1900" "2" "770"]})
助手 function 將字符串(kg 數量)轉換為字符串(lb 數量):
(defn kg->lb [kg-string]
(-> kg-string
parse-long
(* 2.2)
int
str))
最重要的 function 是reduce-kv
。
如果您在鍵中找到"kg"
,您將用"lb"
和 map helper function 替換所有值。
如果您在密鑰中沒有找到"kg"
,您將直接關聯該條目而無需更改。
(reduce-kv (fn [m k v]
(if (re-find #"kg" k)
(assoc m (str/replace k #"kg" "lb")
(map kg->lb v))
(assoc m k v)))
{}
data)
我想我通過了項目要求是不使用字符串庫,除了(str/replace k #"kg" "lb")
,你可以用String/replace
interop: (.replace k "kg" "lb")
。
(defn update-entry [[k v]]
(if (re-find #"kg" k)
[(.replace k "kg" "lb") (map kg->lb v)]
[k v]))
(->> data
(map update-entry)
(into {}))
傳感器版本:
(into {} (map update-entry) data)
我會做一些不同的。 首先,我使用 Java function Long/parseLong
將字符串轉換為整數:
(ns tst.demo.core
(:use demo.core tupelo.core tupelo.test)
(:require
[tupelo.core :as t]
))
(defn parse-vec-longs
[v]
(mapv #(Long/parseLong %) v))
(verify
(is= (parse-vec-longs ["150" "220" "530"])
[150 220 530]))
然后我會編寫代碼將 kg vals 轉換為 lb vals。 最后,只需使用dissoc
去掉 kg 數據,然后assoc
添加新的 lb 數據:
(defn convert-kg-lb
[data]
(let-spy-pretty [kg-vals (get data "weight-kg")
lb-vals (mapv #(Math/round (* 2.2 %)) kg-vals)
result (t/it-> data
(dissoc it "weight-kg")
(assoc it "weight-lb" lb-vals))]
result))
(verify
(let [data-str {"id" ["7215" "74777" "7219"]
"weight-kg" ["150" "220" "530"]
"time-seconds" ["1900" "2" "770"]}
data-parsed (t/map-vals data-str #(parse-vec-longs %))
expected-parsed {"id" [7215 74777 7219]
"weight-kg" [150 220 530]
"time-seconds" [1900 2 770]}
expected-out {"id" [7215 74777 7219]
"weight-lb" [330 484 1166]
"time-seconds" [1900 2 770]}
result (convert-kg-lb data-parsed)]
(is= data-parsed expected-parsed)
(is= (spyx-pretty result) (spyx-pretty expected-out))))
通常,您還會用關鍵字替換所有字符串鍵,因此"lb"
=> :lb
。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.