如何有效处理clojure中的排序数据?

时间:2015-01-28 13:14:13

标签: clojure

我有一系列排序数据,并希望设置邻居标志。例如,对于以下数据,对于任何元素,如果任何邻居的标志为1,则设置 该元素的any-neighbor-flagged为1。我们可以将邻居定义为seq的diff是< = 2,如果diff< = 2,那么它们是邻居。 可能有数百万的数据点。

(def a '({:seq 1 :flag 1} {:seq 2 :flag 0} {:seq 5 :flag 0} {:seq 8 :flag 0} {:seq 10 :flag 1} {:seq 12 :flag 1}))

预期结果是:

({:seq 1 :any-neighbor-flagged 0} {:seq 2 :any-neighbor-flagged 1} {:seq 5 :any-neighbor-flagged 0} {:seq 8 :any-neighbor-flagged 1} 
{:seq 10 :any-neighbor-flagged 1} {:seq 12 :any-neighbor-flagged 1})

2 个答案:

答案 0 :(得分:3)

使用partition,我们可以查看具有相邻上下文的集合。

user=> (partition 3 1 (range 10))
((0 1 2) (1 2 3) (2 3 4) (3 4 5) (4 5 6) (5 6 7) (6 7 8) (7 8 9))

给定该表单中的输入,我们可以使用reduce来累积基于邻居比较的结果。

user=> (pprint/pprint (reduce (fn [acc [i j k]]
                                  (conj acc
                                        (assoc j :any-neighbor-flagged
                                               (if (or (= (:flag i) 1)
                                                       (= (:flag k) 1))
                                                   1 0))))
                              []
                              (partition 3 1 (concat [nil] a [nil]))))
[{:any-neighbor-flagged 0, :seq 1, :flag 1}
 {:any-neighbor-flagged 1, :seq 2, :flag 0}
 {:any-neighbor-flagged 0, :seq 5, :flag 0}
 {:any-neighbor-flagged 1, :seq 8, :flag 0}
 {:any-neighbor-flagged 1, :seq 10, :flag 1}
 {:any-neighbor-flagged 1, :seq 12, :flag 1}]

答案 1 :(得分:0)

基本思想是映射3个序列 - 原始序列,向左移1,向右移1:

(defn set-flags [coll]
  (map
    (fn [curr {nf :flag} {pf :flag}]
      (-> curr
          (dissoc :flag)
          (assoc :any-neighbor-flagged (if (or (= pf 1) (= nf 1)) 1 0))))
    coll
    (concat [{}] (drop-last coll))
    (concat (rest coll) [{}])))

(set-flags a) ; => ({:any-neighbor-flagged 0, :seq 1} {:any-neighbor-flagged 1, :seq 2} {:any-neighbor-flagged 0, :seq 5} {:any-neighbor-flagged 1, :seq 8} {:any-neighbor-flagged 1, :seq 10} {:any-neighbor-flagged 1, :seq 12})

插图(为简单起见,仅显示:flag的值):

(1 0 0 0 [1] 1) ; original seq
---------------
  (1 0 0 [0] 1) ; shifted to right
(0 0 0 1 [1])   ; shifted to left

现在在map函数中,我们还为输入的每个元素(可能是空映射)留下了邻居和右邻居。基于此,可以轻松为:any-neighbor-flagged设置正确的值。