迭代clojure映射对(循环)

C.A*_*C.A 7 dictionary loops clojure

我有一系列像这样的地图对(目前大约17000对)

(def myseq '({:name "Peter" :rank 2222} {:name "Anna" :rank 111}))
Run Code Online (Sandbox Code Playgroud)

我想用特定的对将特定的对过滤成新的序列

(filter (fn [x] (> x 222)) (:rank (first myseq)))
Run Code Online (Sandbox Code Playgroud)

我一直试图像这样迭代循环,但继续线程死亡.此外,如果我在单个地图集合上使用过滤器,它只返回一个新序列,不确定我是否需要在这里创建一个?

(defn remove-lower [number myseq]
    (loop [i 0]
        (if (= i (count file))
            (println "done")
            (filter [x] (> x number))
                (:rank (first myseq))))
    (recur (rest myseq))))
Run Code Online (Sandbox Code Playgroud)

Finnally正在循环以获得新的对序列的最有效方式?

最好,J

Joo*_*aat 8

这里不需要循环/重复.过滤器已为您迭代seq:

(filter (fn [entry] (> (:rank entry) 220)) myseq)
Run Code Online (Sandbox Code Playgroud)

  • `(filter#(>(:rank%)220)myseq)` (5认同)

iva*_*ant 6

首先要知道的是(大部分)clojure中的数据结构是不可变的,大多数函数都是功能性的.这意味着,他们没有副作用.在您的情况下filter,不会以任何方式更改序列,它将返回一个新序列,仅包含未过滤的项目.

因此,要过滤myseq您需要执行以下操作:

(def filtered-seq (filter (fn [x] ...) myseq))
Run Code Online (Sandbox Code Playgroud)

过滤器将重复调用该函数,绑定x到当前过滤的项目myseq.也就是说,第一次被束缚{:name "Peter" :rank 2222},然后到{:name "Anna" :rank 111}.在filtered-seq将只包含元素,该函数返回真.myseq不会被修改!

所以,你想只留下:rank高于222的元素:

(filter (fn [x] (> (:rank x) 222)) myseq)
Run Code Online (Sandbox Code Playgroud)

而已.关于过滤器的另一件事是,它是懒惰的.也就是说,返回集合中的项目仅在需要时才"实现"(或计算).

你不需要使用loop这个,就像filter工作很好,并且loop不是懒惰.

也就是说,你的loop工作没有用,因为它有几个问题:

  1. recur在外面loop.在这种情况下,clojure将循环回函数的开头.
  2. 你需要构造一个返回值,你需要维护"当前"元素
  3. 你需要正确检查结束条件

代码可能看起来像这样(未经测试):

(defn remove-lower [number myseq]
  (loop [sq myseq res []]
     (if (empty? sq)
         res
         (let [current (first sq)]
           (if (> (:rank current) number)
              (recur (rest sq) (conj res current))
              (recur (rest sq) res))))))
Run Code Online (Sandbox Code Playgroud)

请注意:

  1. recur 现在在里面 loop
  2. res包含返回值并sq包含当前左侧序列
  3. 每个都recur传递新值sqres下一次迭代
  4. sq每次迭代都会"缩小",所以循环最终会退出,除非myseq是无限的.对比这个filter,处理无限序列就好了.

正如你所看到的那样,阅读起来比较困难而且不那么普遍,filter而且也很渴望(不是懒惰).