Dictionary Clojure迭代向量并向前看/向后看
我必须迭代一个向量,而这个向量又有映射作为它的项。我需要比较下一张地图,有时我需要看看我们之前看过的地图上有什么。因此,有必要具备某种前瞻/落后功能。我目前的方法是可行的,但我想它是丑陋的、单一的Clojure,我认为必须有更好的(更规范的)方法来实现这一点Dictionary Clojure迭代向量并向前看/向后看,dictionary,clojure,iteration,Dictionary,Clojure,Iteration,我必须迭代一个向量,而这个向量又有映射作为它的项。我需要比较下一张地图,有时我需要看看我们之前看过的地图上有什么。因此,有必要具备某种前瞻/落后功能。我目前的方法是可行的,但我想它是丑陋的、单一的Clojure,我认为必须有更好的(更规范的)方法来实现这一点 (let [result (apply str (map (fn [{position-before :position compound-before :compund } ; previous term (unfortunately w
(let [result (apply str (map (fn [{position-before :position compound-before :compund } ; previous term (unfortunately we need to compare all three)
{:keys [word position line tag stem compound grammarpos] :or {grammarpos "0" stem "" } } ; this maps to the current word
{position-ahead :position compound-ahead :compound line-ahead :line}] ; this is for lookahead
(do some stuff)) ;; now we have position, which is our current position, position-before and position-after to compare with each other
;; this is how we map:
(into '[{}] (conj grammar '[{}]))
(next (into '[{}] (conj grammar '[{}])))
(next (next (into '[{}] (conj grammar '[{}]))))))])
对于数据示例的请求,这是向量的一部分:
[{:tag "0", :position "0", :line "0", :stem "dev", :grammarpos "2625", :word "deva"} {:tag "0", :position "0", :line "0", :stem "deva", :grammarpos "4", :word "deva"}]
工作是比较位置、化合物等的值,有时向前看,有时向后看 可以迭代向量的
分区
,大小为3,步长为1。然后,对于向量中的每个元素,您还可以获得之前和之后的值,您可以在使用for
或reduce
进行迭代时进行研究
一些示例:此外,如果每个项目都需要前面和后面的所有项目,则可以将
与解构结合起来,进行列表理解
例如:
user> (def items [:a :b :c :d :e :f :g])
#'user/items
user> (for [index (range (count items))
:let [[before [current & after]] (split-at index items)]]
{:before before :current current :after after})
({:before (), :current :a, :after (:b :c :d :e :f :g)}
{:before (:a), :current :b, :after (:c :d :e :f :g)}
{:before (:a :b), :current :c, :after (:d :e :f :g)}
{:before (:a :b :c), :current :d, :after (:e :f :g)}
{:before (:a :b :c :d), :current :e, :after (:f :g)}
{:before (:a :b :c :d :e), :current :f, :after (:g)}
{:before (:a :b :c :d :e :f), :current :g, :after nil})
您只需在每个项的索引处逐个拆分集合,并从结果中获取第一项(之前)、第二项的第一项(当前)、第二项的其余部分(之后)
还有一种可读性稍差的方式(但对于大型集合来说可能更高效,因为它不会在每个步骤上执行take
/drop
,而是在coll中添加/删除单个项)
如果你想做真正复杂的事情,也许会是一个更好的解决方案
例如,假设您从以下内容开始:
(def x
[{:tag "0" :dups 0}
{:tag "1" :dups 0}
{:tag "1" :dups 0}
{:tag "3" :dups 0}])
您的要求是增加具有相同名称的所有连续标记的dups计数器,并在它们之间添加一个“--”标记
使用拉链,解决方案将如下所示:
(require '[clojure.zip :as zip :refer [root node]])
(defn complex-thing [zip]
(if (zip/end? zip) ;; are we done?
(root zip) ;; return the "updated" vector
(let [current-node (node zip)
before-node (node (zip/prev zip))] ;; you can access any map in the vector, both before or after
(if (= (:tag current-node) (:tag before-node))
(recur (-> zip
zip/prev ;; move to the previous map
(zip/edit update :dups inc) ;; increment it
zip/next ;; move back to the current map
(zip/edit update :dups inc)
(zip/insert-left {:tag "----"}) ;; insert "---" before the current tag
zip/next)) ;; move to next map to process
(recur (zip/next zip))))))
(complex-thing (zip/next (zip/next (zip/vector-zip x)))) ;; start from the second element of the vector
[{:tag "0", :dups 0}
{:tag "1", :dups 1}
{:tag "----"}
{:tag "1", :dups 1}
{:tag "3", :dups 0}]
你能在你的问题中添加一个小的/有代表性的数据集吗?如果你能展示你的地图矢量中有什么以及你想从中得到什么,你可能会得到更明确的帮助。添加了它们,希望能澄清问题。
(require '[clojure.zip :as zip :refer [root node]])
(defn complex-thing [zip]
(if (zip/end? zip) ;; are we done?
(root zip) ;; return the "updated" vector
(let [current-node (node zip)
before-node (node (zip/prev zip))] ;; you can access any map in the vector, both before or after
(if (= (:tag current-node) (:tag before-node))
(recur (-> zip
zip/prev ;; move to the previous map
(zip/edit update :dups inc) ;; increment it
zip/next ;; move back to the current map
(zip/edit update :dups inc)
(zip/insert-left {:tag "----"}) ;; insert "---" before the current tag
zip/next)) ;; move to next map to process
(recur (zip/next zip))))))
(complex-thing (zip/next (zip/next (zip/vector-zip x)))) ;; start from the second element of the vector
[{:tag "0", :dups 0}
{:tag "1", :dups 1}
{:tag "----"}
{:tag "1", :dups 1}
{:tag "3", :dups 0}]