我必须迭代一个矢量,而矢量又将地图作为其项目。我需要比较下一张地图,有时我需要查看我们之前看过的地图。所以有必要展望未来/看后面的功能。我当前的方法是有效的,但我想这是丑陋的,单一的Clojure,我认为必须有更好的(更规范的)方法来实现这一点。
(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"}]
工作是比较位置,复合等的值,有时向前看,有时看后面。
答案 0 :(得分:12)
你可以迭代你的向量的partition
,大小为3,步长为1.然后,对于向量中的每个元素,你也可以得到之前和之后你可以在迭代时学习for
或reduce
。
答案 1 :(得分:3)
如果您需要每个项目的所有前面和后面的项目,您可以将for
列表理解与解构结合起来。
例如:
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)< / p>
user> (take (count items)
(iterate
(fn [[before current after]]
[(conj before current) (first after) (rest after)])
[[] (first items) (rest items)]))
([[] :a (:b :c :d :e :f :g)]
[[:a] :b (:c :d :e :f :g)]
[[:a :b] :c (:d :e :f :g)]
[[:a :b :c] :d (:e :f :g)]
[[:a :b :c :d] :e (:f :g)]
[[:a :b :c :d :e] :f (:g)]
[[:a :b :c :d :e :f] :g ()])
答案 2 :(得分:1)
如果你想做一些非常复杂的事情,或许zippers将是一个更好的解决方案。
例如,假设您从以下开始:
(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}]