首先,我是12岁的学生,在The Iron Yard学习Java后端工程。该课程由大约60%的Java,25%的JavaScript和15%的Clojure组成。
我遇到了以下问题(在评论中概述):
;; Given an ArrayList of words, return a HashMap> containing a keys for every
;; word's first letter. The value for the key will be an ArrayList of all
;; words in the list that start with that letter. An empty string has no first
;; letter so don't add a key for it.
(defn index-words [word-list]
(loop [word (first word-list)
index {}]
(if (contains? index (subs word 0 1))
(assoc index (subs word 0 1) (let [words (index (subs word 0 1))
word word]
(conj words word)))
(assoc index (subs word 0 1) (conj nil word)))
(if (empty? word-list)
index
(recur (rest word-list) index))))
我能够使用zipmap
解决类似的问题,但我很肯定我错过了这个问题。代码编译但无法运行。
具体来说,我未能在' if'的错误条款中更新我的hashmap索引。
我已经在REPL中测试了这个函数的所有组件,它们是孤立的。但是我正在努力把它们放在一起。
供您参考,以下是调用word-list的代码。
(let [word-list ["aardvark" "apple" "zamboni" "phone"]]
(printf "index-words(%s) -> %s\n" word-list (index-words word-list)))
不是从社区获得有效的解决方案,我希望能有一些指示让我的大脑朝着正确的方向前进。
答案 0 :(得分:5)
函数assoc
不会修改index
。您需要使用assoc
返回的新值。 conj
也是如此:它不会修改您传递的地图。
我希望,这个答案具有你期望获得的性质:只是你问题所在的指针。
顺便说一句:如果你可以使用PersistentList
,那么在使用reduce
而不是loop
和recur
时,这就变成了单行。一个有趣的功能可能是update-in
。
享受Clojure的乐趣。
答案 1 :(得分:0)
group-by
功能可以满足您的需求。
first
作为其区分函数参数。它
返回字符串的第一个字符,如果没有字符串,则返回nil
:
(first word)
比(subs word 0 1)
简单。dissoc
删除密钥nil
的条目。 你很少需要在clojure中使用明确的loop
。最常见的控制模式已在group-by
等函数中捕获。这些函数具有函数和可能的集合参数。最常见的示例是map
和reduce
。 Clojure cheat sheet是对他们最有用的指南。