如何根据键名有条件地更新Clojure映射中的键与值?
解决Clojure映射中含"kg"键的转换问题
需求说明
遍历键为字符串的Clojure映射:
- 若键包含"kg"字样,将键中的"kg"替换为"lb",同时将对应值的每个元素(字符串形式的数字)乘以2.2后取整,再转回字符串。
- 不包含"kg"的键值对保持原样。
示例输入
{"id" ("7215" "74777" "7219"), "weight-kg" ("150" "220" "530"), "time-seconds" ("1900" "2" "770")}
期望输出
{"id" ("7215" "74777" "7219"), "weight-lb" ("330" "484" "1166"), "time-seconds" ("1900" "2" "770")}
注:示例输出中的"485""1168"为计算笔误,实际220×2.2=484,530×2.2=1166
实现代码
(defn convert-kg-to-lb [m] (reduce-kv (fn [acc k v] (if (re-find #"kg" k) ;; 处理含"kg"的键值对:替换键、转换值 (let [;; 替换键中的"kg"为"lb"(不依赖clojure.string库) kg-index (.indexOf k "kg") new-key (str (subs k 0 kg-index) "lb" (subs k (+ kg-index 2))) ;; 转换值:字符串转数字→乘2.2→取整→转回字符串 new-value (map #(str (Math/round (* (Double/parseDouble %) 2.2))) v)] (assoc acc new-key new-value)) ;; 非目标键值对直接加入结果映射 (assoc acc k v))) {} ;; 初始空映射,用于逐步构建结果 m))
代码解释
reduce-kv的核心作用:遍历原映射的每个键值对,逐个处理并构建新的映射,这是Clojure中处理映射条件更新的标准方式。- 键替换逻辑:通过Java字符串的
.indexOf和subs方法实现"kg"到"lb"的替换,避免使用clojure.string库,符合项目要求。 - 值转换逻辑:
- 将每个字符串形式的数字转为
Double类型; - 乘以2.2后用
Math/round取整(匹配示例中的整数输出); - 转回字符串保持原数据格式。
- 将每个字符串形式的数字转为
你之前尝试的问题分析
kg->lb函数:参数设计不合理,且使用map处理单个键值对逻辑错误,无法构建完整的新映射。kg2->lb2函数:reduce-kv的回调函数参数错误(未正确接收键k和值v),update用法缺失目标键,无法正确修改映射。map/for的尝试:这两个函数会生成序列而非单个映射,每次update返回的是独立的新映射,最终得到的是包含多个映射或nil的序列,不是预期的结果。
内容的提问来源于stack exchange,提问作者triplej
相关产品推荐
相关产品推荐

