【问题标题】:Clojure iterate a vector and look ahead/look behingClojure 迭代一个向量并向前看/向后看
【发布时间】:2016-05-11 17:41:01
【问题描述】:

我确实必须遍历一个向量,该向量又将地图作为其项目。我需要比较下一张地图,有时我需要查看我们之前查看的地图中的内容。因此,有必要具有某种前瞻性/后视功能。我目前的方法有效,但我认为它是丑陋的、单一的 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 '[{}]))))))])

至于data-example的请求,这是vector的一部分:

[{:tag "0", :position "0", :line "0", :stem "dev", :grammarpos "2625", :word "deva"} {:tag "0", :position "0", :line "0", :stem "deva", :grammarpos "4", :word "deva"}]

工作是比较位置、复合等的值,有时向前看,有时向后看。

【问题讨论】:

  • 您能否在您的问题中添加一个小型/代表性数据集?如果您可以显示地图矢量中的内容以及您希望从中返回的内容,您可能会获得更明确的帮助。
  • 已添加,希望有助于澄清问题。

标签: dictionary clojure iteration


【解决方案1】:

如果你想做非常复杂的事情,也许zippers 会是一个更好的解决方案。

例如,假设您从以下开始:

(def x
  [{:tag "0" :dups 0}
   {:tag "1" :dups 0}
   {:tag "1" :dups 0}
   {: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}]

【讨论】:

    【解决方案2】:

    此外,如果您需要每个项目的所有前面和后面的项目,您可以将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)

    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 ()])
    

    【讨论】:

      【解决方案3】:

      您可以迭代向量的 partition,大小为 3,步长为 1。然后对于向量中的每个元素,您还可以在使用 @ 迭代时获得之前和之后的内容987654323@或reduce

      一些例子:https://clojuredocs.org/clojure.core/partition

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2017-08-29
        • 2011-01-28
        • 1970-01-01
        相关资源
        最近更新 更多