在clojure中从数组构建一个hashmap

时间:2016-09-03 13:52:20

标签: clojure hashmap zipmap

首先,我是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)))

不是从社区获得有效的解决方案,我希望能有一些指示让我的大脑朝着正确的方向前进。

2 个答案:

答案 0 :(得分:5)

函数assoc不会修改index。您需要使用assoc返回的新值。 conj也是如此:它不会修改您传递的地图。

我希望,这个答案具有你期望获得的性质:只是你问题所在的指针。

顺便说一句:如果你可以使用PersistentList,那么在使用reduce而不是looprecur时,这就变成了单行。一个有趣的功能可能是update-in

享受Clojure的乐趣。

答案 1 :(得分:0)

group-by功能可以满足您的需求。

  • 您可以使用first作为其区分函数参数。它 返回字符串的第一个字符,如果没有字符串,则返回nil(first word)(subs word 0 1)简单。
  • 使用dissoc删除密钥nil的条目。

你很少需要在clojure中使用明确的loop。最常见的控制模式已在group-by等函数中捕获。这些函数具有函数和可能的集合参数。最常见的示例是mapreduceClojure cheat sheet是对他们最有用的指南。