如何创建此哈希图?

时间:2019-07-05 11:29:00

标签: clojure hashmap

基本上我想做的是打印一个包含键的哈希表,这些键是字符串中的字符,并且这些键的值为1。例如,字符串“ aabbce”应提供字典{:a 1:b 1 :c 1}。 以下是我的尝试,但只显示空的哈希图

(defn isValid [s]
    (def dict {})

    (map (fn [x] ((assoc dict :x 1))) (seq s))

    (println dict)

)

4 个答案:

答案 0 :(得分:5)

另一种方法是:

(zipmap (map (comp keyword str) "abc") (repeat 1))

;;=> { :a 1 :b 1 :c 1 }

答案 1 :(得分:2)

您已经违反了Clojure编程的几项准则:

  • 不打印结果-将其返回。
  • 请勿对本地人使用def。使用let
  • 不要强制使用关键字。地图键不必是关键字。
  • 不要尝试分配名称。使用功能的修改结果。

要在这里做最后一件事,请使用reduce而不是mapseq是多余的:mapreduce之类的函数会将字符串视为字符序列。所以...

(defn isValid [s]
  (reduce (fn [dict x] (assoc dict x 1)) {} s))

例如...

=> (isValid "aabbce" )
{\a 1, \b 1, \c 1, \e 1}

本地dict和初始值{}已被reduce捕获。


为什么要映射到1?这只是变相的场景吗?如果是这样,...

(defn isValid [s]
  (set s))

或者只是...

(def isValid set)

例如

=> (isValid "aabbce" )
#{\a \b \c \e}

您将在函数式编程中找到它。样板代码像奇努克风中的雪一样融化。


最后一个琐碎的抱怨。 isValid是骆驼的情况。 Clojure约定是

  • 烤肉串案和
  • 对谓词进行?跟踪。

valid?而不是isValid

答案 2 :(得分:1)

> (into {} (for [c "aabbce"] [(keyword (str c)) 1]))
{:a 1, :b 1, :c 1, :e 1}

into {} ... sequence of pairs ...通常是创建哈希图的便捷方法。例如

> (into {} [[:x 1] [:y "foo"]])
{:x 1, :y "foo"}

for [item collection] [(key-from item) (value-from item)]是遍历集合以创建键值对列表的一种好方法。

> (for [color ["red" "blue" "green"]] [(clojure.string/upper-case color) (count color)])
(["RED" 3] ["BLUE" 4] ["GREEN" 5])

我发现将它们放在一起通常是创建哈希图的诀窍:

> (into {} (for [color ["red" "blue" "green"]] [(clojure.string/upper-case color) (count color)]))
{"RED" 3, "BLUE" 4, "GREEN" 5}

答案 3 :(得分:0)

有很多方法可以利用Clojure核心库中的大量功能来实现此功能。这是Clojure的每个新开发人员都会遇到的常见问题之一:您认为您需要自己编写一个函数,但是实际上已经存在一些东西,只是您还不知道它的名字,所以{{3 }}可能会派上用场。

让我们从字符串aabbce开始。您想删除重复项,因此(set "aabbce")会将字符串作为字符集读取,并从中创建一个字符集。您可以使用map函数获取每个字符并将其变成关键字。问题在于keyword函数使用字符串而不是字符,因此我们需要首先在每个字符上使用str

一旦我们有了一系列关键字,构造地图的一种简单方法就是使用frequencies函数,它将使用关键字作为关键字,为关键字集合中的每个元素创建一个哈希图,以及它作为值出现在集合中的次数,并且由于我们已经删除了重复项,因此可以保证每个值都只是1

将所有内容放在一起:

(defn is-valid? [s]
  (frequencies
   (map (comp keyword str)  ;; Turns \a into :a for every letter in the set
        (set s))))          ;; remove duplicates, yields: (\a, \b, \c, \e)

;; or, using the ->> macro:

(defn is-valid? [s]
  (->> (set s)                   ;; turn string into set of chars
       (map (comp keyword str))  ;; turn chars into keywords
       frequencies))             ;; compute occurrences hash-map

;; (println (is-valid? "aabbce"))
;; => {:a 1, :b 1, :c 1, :e 1}

现在,名称​​ isValid 表示您希望将此函数用作谓词(例如,根据输入内容返回truefalse)。也许想构建一个函数来检查字符串是否由某些字母组成?