2012-04-11 65 views
0

我不认为按键是?下面的函数按照我期望的方式工作。首先,这里是输入数据。循环如果并且直到结果发现然后退出

从中导出cmp-val的数据: [“2”“000-00-0000”“TOAST”“FRENCH”“”“M”“26-Aug-99”“”“ALL CARE PLAN”“医疗“] 缺少密钥(ssn)的数据。 [“000-00-0000”“TOAST”“FRENCH”“RE-PART B - 已保存”]

问题是,如果我输入其中一个000-00-0000其他东西,我应该 看到那个连接到一个日志向量。我没有,而且我没有看到它印有“如果不是空的”。

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

    (let [ret-rc 
     (for [csv-row csv-data 
       :let [rc (is-a-in-b cmp-val cmp-idx csv-row)] 
       :when (true? (is-a-in-b cmp-val cmp-idx csv-row))] 
      rc)] 
     (vec ret-rc))) 

(defn test-key-inclusion 
    "Accepts csv-data file 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] 

    (reduce 
     (fn [out-log csv-row1] 
      (let [cmp-val (nth csv-row1 pkey-idx1 nil)] 
       (doseq [csv-row2 csv-data2] 
        (let [temp-rc (key-pres? cmp-val pkey-idx2 csv-row2)] 
         (if-not (empty? temp-rc) 
          (println cmp-val, " ", (nth csv-row2 pkey-idx2 nil), " ", temp-rc)) 
         (if (nil? temp-rc) 
         (conj out-log cmp-val)))))) 
     [] 
     csv-data1)) 

我想要的功能是通过clojure-csv(矢量矢量)返回的遍历数据。如果可以在csv-row的cmp-idx位置找到cmp-val,我希望 被分配给rc,并且终止该循环。

我该如何修复for循环,如果不能,我可以使用什么循环机制来实现这一点?

谢谢。

回答

1
  • 你不需要true?,它专门检查布尔值true的值;
  • 不重复调用is-a-in-b;
  • 它会更习惯于使用a-in-b?作为fn名称;
  • 我建议简化代码,你不需要那个let

代码:

(vec (for [csv-row csv-data 
      :let [rc (a-in-b? cmp-val cmp-idx csv-row)] 
      :when rc)] 
     rc)) 

但是,这只是对代码风格的一些一般性的评论......你在这里实施的是只是一个简单的filter

(vec (filter #(a-in-b? cmp-val cmp-idx %) csv-data)) 

此外,这不仅会返回第一场比赛,而且还会比赛结束。如果我正确地阅读你的问题,你只需要找到第一场比赛?然后使用some

(some #(a-in-b? cmp-val cmp-idx %) csv-data) 

UPDATE

重读你的问题,我让你考虑for是一个循环结构的感觉。这不是 - 它是一个列表理解,产生一个懒惰的seq。要编写循环来控制迭代的时间,您必须使用loop-recur。但在Clojure中,除了性能之外,你几乎不需要为自己写循环。在所有其他情况下,您从clojure.core组成高阶函数。

+0

我用于循环积累,但我使用减少修复我的问题。 – octopusgrabbus 2012-04-12 12:01:50