Как создать этот hashmap? - PullRequest
0 голосов
/ 05 июля 2019

В основном я пытаюсь напечатать хэш-карту, содержащую ключи, которые являются символами в строке, и эти ключи имеют значение 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 ]

5 голосов
/ 05 июля 2019

другой способ:

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

;;=> { :a 1 :b 1 :c 1 }
2 голосов
/ 06 июля 2019

Вы нарушили несколько правил программирования Clojure:

  • Не печатать результат - вернуть его.
  • Не используйте def для местных жителей. Используйте let.
  • Не заставляйте использовать ключевые слова. Ключи карты не обязательно должны быть ключевыми словами.
  • Не пытайтесь назначать имена. Используйте исправленный результат функции.

Чтобы сделать последнее, используйте reduce вместо map. И seq является избыточным: такие функции, как map и reduce будут обрабатывать строку как последовательность символов. Итак ...

(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.

1 голос
/ 05 июля 2019
> (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}
0 голосов
/ 06 июля 2019

Существует множество способов реализовать это, используя большое количество функций в базовой библиотеке Clojure. Это одна из распространенных проблем, возникающих с каждым новым разработчиком, приходящим в Clojure: вы думаете, что вам нужно написать функцию самостоятельно, но на самом деле что-то уже существует, просто вы еще не знаете ее имя, поэтому Шпаргалка Clojure может пригодиться.

Давайте начнем со строки 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 предполагает, что вы хотите использовать эту функцию в качестве предиката (например, return true или false в зависимости от ввода). Может быть, хотите построить функцию, которая проверяет, состоит ли строка из определенных букв?

...