2012-04-11 45 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