【问题标题】:Migrating Reduce To Map将 Reduce 迁移到 Map
【发布时间】:2012-04-13 14:43:33
【问题描述】:

我的问题是如何使用 map 和可能的 doseq 重写以下 reduce 解决方案?我在使用以下解决方案时遇到了很多麻烦。

该解决方案是解决以下问题。具体来说,我有两个由 clojure-csv 解析的 csv 文件。每个向量的向量可以称为 bene-data 和 gic-data。我想获取每行 bene-data 中的一列中的值,并查看该值是否是 gic-data 中一行中的另一列。我想将 gic-data 中找不到的那些 bene-data 值累积到一个向量中。我最初尝试累积到地图中,并且在尝试调试打印时从堆栈溢出开始。最终,我想将这些数据与一些静态文本结合起来,然后吐出到一个报告文件中。

以下功能:

(defn is-a-in-b
    "This is a helper function that takes a value, a column index, and a 
     returned clojure-csv row (vector), and checks to see if that value
     is present. Returns value or nil if not present."
    [cmp-val col-idx csv-row]

    (let [csv-row-val (nth csv-row col-idx nil)]
        (if (= cmp-val csv-row-val)
            cmp-val
            nil)))

(defn key-pres?
    "Accepts a value, like an index, and output from clojure-csv, and looks
     to see if the value is in the sequence at the index. Given clojure-csv
     returns a vector of vectors, will loop around until and if the value
     is found."

    [cmp-val cmp-idx csv-data]
    (reduce
        (fn [ret-rc csv-row]
            (let [temp-rc (is-a-in-b cmp-val cmp-idx csv-row)]
                (if-not temp-rc
                    (conj ret-rc cmp-val))))
        [] 
        csv-data))


(defn test-key-inclusion
    "Accepts csv-data param and an index, a second csv-data param and an index,
     and searches the second csv-data instances' rows (at index) to see if
     the first file's data is located in the second csv-data instance."

    [csv-data1 pkey-idx1 csv-data2 pkey-idx2 lnam-idx fnam-idx]

    (reduce
        (fn [out-log csv-row1]
            (let [cmp-val (nth csv-row1 pkey-idx1 nil)
                  lnam (nth csv-row1 lnam-idx nil)
                  fnam (nth csv-row1 fnam-idx)
                  temp-rc (first (key-pres? cmp-val pkey-idx2 csv-data2))]

            (println (vector temp-rc cmp-val lnam fnam))
            (into out-log (vector temp-rc cmp-val lnam fnam))))
         []
         csv-data1))

代表我尝试解决这个问题。我经常在尝试使用doseq和map时碰壁,因为我无处可积累结果数据,除非我使用循环recur。

【问题讨论】:

    标签: clojure


    【解决方案1】:

    此解决方案将第 2 列的所有内容一次读取到一个集合中(因此,它是非惰性的)以便于编写。它还应该比为第 1 列的每个值重新扫描第 2 列执行得更好。如果第 2 列太大而无法在内存中读取,请根据需要进行调整。

    (defn column
      "extract the values of a column out of a seq-of-seqs"
      [s-o-s n]
      (map #(nth % n) s-o-s))
    
    (defn test-key-inclusion
      "return all values in column1 that arent' in column2"
      [column1 column2]
      (filter (complement (into #{} column2)) column1))
    
    user> (def rows1 [[1 2 3] [4 5 6] [7 8 9]])
    #'user/rows1
    
    user> (def rows2 '[[a b c] [d 2 f] [g h i]])
    #'user/rows2
    
    user> (test-key-inclusion (column rows1 1) (column rows2 1))
    (5 8)
    

    【讨论】:

    • 也许是(defn test-key-inclusion [column1 column2] (remove (set column2) column1))?帮助自己。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-07-07
    • 1970-01-01
    • 1970-01-01
    • 2013-05-25
    相关资源
    最近更新 更多