Clojure Atoms,我想返回最终值

时间:2016-10-08 21:59:51

标签: clojure

好的,所以在我的函数中添加一个数组,我保留一些东西来返回一个字符串作为键,列表作为值的哈希映射。我想只得到最终值并将其作为参数传递给另一个函数。

下面是我试图将其翻译成clojure的java代码

contents = documentContent.split("[ ,\\.]+");
        for(int i = 0; i < contents.length; i++) {
            String word = contents[i];
            if(index.containsKey(word)) {
                index.get(word).add(i);
            } else {
                List<Integer> list = new ArrayList<>();
                list.add(i);
                index.put(word, list);
            }
        }

Clojure代码到目前为止它有点工作,但我不能返回最终值并将其传递给另一个函数

(defn indexFinder [contents] 
  (let [mem (def xs (atom {}))]
    (map-indexed
      (fn [index element]
        (if (contains? @xs element)
          (swap! xs assoc element (conj (@xs element) index))
          (swap! xs assoc element [index])))
      contents)))

3 个答案:

答案 0 :(得分:2)

以下是我的写作方式:

(defn index-finder [s]
  (->> (clojure.string/split s #"[ ,\\.]+")
       (map-indexed list)
       (reduce (fn [acc [i w]]
                 (update acc w conj i)) {})))

使用示例:

(index-finder "aaa bbb ccc ddd aaa bbb") ;; {"aaa" (4 0), "bbb" (5 1), "ccc" (2), "ddd" (3)}

注意:在开始学习Clojure时,人们往往会认为他经常需要原子。

答案 1 :(得分:1)

我建议首先反对原子。

(->> (zipmap (range) contents) ;contents is a list of words
     (reduce (fn [index [location word]]
               (merge-with concat index {word (list location)})) {}))

示例:

user=> (def contents (clojure.string/split "hello there these are some words and some repeated words" #" "))
#'user/contents
user=> contents
["hello" "there" "these" "are" "some" "words" "and" "some" "repeated" "words"]

user=>     (->> (zipmap (range) contents)
  #_=>          (reduce (fn [index [location word]]
  #_=>                    (merge-with concat index {word (list location)})) {}))
{"hello" (0), "some" (7 4), "there" (1), "and" (6), "are" (3), "these" (2), "words" (9 5), "repeated" (8)}

答案 2 :(得分:1)

原始的indexFinder缺少一个强制其副作用(更新原子)的doall。并且还不需要声明mem。有了它,工作版本可能如下所示:

(defn indexFinder [contents] 
  (let [xs (atom {})]
    (doall (map-indexed
            (fn [index element]
              (if (contains? @xs element)
                (swap! xs assoc element (conj (@xs element) index))
                (swap! xs assoc element [index])))
            contents))
    @xs))

您还可以简化地图索引部分:

(defn indexFinder [contents] 
  (let [xs (atom {})]
    (doall (map-indexed
            (fn [i e] (swap! xs update e conj i))
            contents))
    @xs))

或者如果你不想依赖副作用,你可以使用它(类似于Brandon的答案,但使用分组):

(defn index-finder [contents]
  (->> (zipmap (range) contents)
       (group-by last)
       (fmap (partial map first))))

其中fmap用于映射函数值(参见algo.generic):

(defn fmap [f m]
  (into (empty m) (for [[k v] m] [k (f v)])))