4

我的问题是如何捕获发生匹配的向量行的索引?在下面的代码中,我做错了什么?

我有一个向量的向量

(def v1 [[44 2 3 4 5][1 6 7 5 10][11 12 13 14 15]])

列索引和比较值

(def cmp-val1 11)
(def col-idx 0)

我想返回比较返回 true 的行索引。在 col-idx = 0 和 cmp-val1 = 11 的情况下,我应该看到 (first row-num) 返回 2,它返回 1。

(defn ret-match-row
    "Return the index of the row, in which the cmp-val is found.
     It is okay to increment 0."

    [in-seq cmp-val col-idx]

    (let [rn 0]
        (let [row-num
            (for [seq-row in-seq
                    :let [local-row-num (inc rn)]
                    :when (= cmp-val (nth seq-row col-idx nil))]

                local-row-num)]

            (first row-num))))

来自 lein repl:

bene-csv.core=> (ret-match-row v1 cmp-val1 col-idx)
1
4

4 回答 4

3
=> (defn ret-match-row
      [coll cmp idx]
      (keep-indexed (fn [i v] (if (= cmp (get v idx)) i)) coll))

=> (ret-match-row v1 11 0)
(2)
于 2012-05-03T23:08:55.173 回答
3

一个灵活的答案来自于将其分成三个不同的问题并将它们组合起来。

  • 创建您寻求的数据
  • 找到你想要的数据
  • 呈现它应该看起来的样子。

首先我们通过添加行号给行编号

(map vector v1 (range))

然后过滤掉不包含您想要的数字的行:

(filter (fn [[data index]] (some #{11} data)) (map vector v1 (range)))
> ([[11 12 13 14 15] 2])

在这里,我使用了一个技巧,即集合是测试其输入是否包含在集合中的函数,这允许它测试多个值:

(filter (fn [[data index]] (some #{11 44} data)) (map vector v1 (range)))
> ([[44 2 3 4 5] 0] [[11 12 13 14 15] 2])

那么既然你只想知道它在哪里匹配而不是什么匹配我们过滤掉它:

(map second (filter (fn [[data index]] (some #{11 44} data)) (map vector v1 (range))))
> (0 2)


为了把它包装成一个很好的函数,我们写下步骤:

(defn with-row-numbers [col] (map vector col (range)))
(defn find-my-rows [rows goals] 
   (filter (fn [[data index]] (some (set goals) data)) rows)) 
(defn present-rows [rows] (map second rows))

然后组成它们:

(defn ret-match-row [data rows]
  (-> data 
   (with-row-numbers) 
   (find-my-rows rows) 
   (present-rows)))

(ret-match-row v1 [11])
(2)

抱歉,我忍不住让它与多个值一起工作,这是一种习惯。

(ret-match-row v1 [11 15 44])
> (0 2)
于 2012-05-03T23:25:52.317 回答
1

可能有其他方法可以满足您的要求,但您可以使用循环/递归来实现您所追求的迭代:

(defn ret-match-row [rows val col-idx]                                                                              
  (loop [[row & rows] rows                                                                                          
         pos 0]                                                                                                     
    (cond                                                                                                           
      (not row)                                                                                                     
      nil                                                                                                           
      (= val (nth row col-idx))                                                                                     
      pos                                                                                                           
      :not-found                                                                                                    
      (recur rows (inc pos)))))                                                                                     

(ret-match-row [[44 2 3 4 5]                                                                                        
                [1 6 7 8 10]                                                                                        
                [11 12 13 14 15]]                                                                                   
               11                                                                                                   
               0)                                                                                                   

;; => 2

您还遇到了 Clojure 的不变性 - (inc rn) 实际上并没有修改 rn。loop / recur 解决方案也使用 inc ,但它将 inc 的结果传递给循环的下一次迭代。

Clojure 的 for (list comprehension) 形式也将循环遍历序列中的所有值,从而产生一个新序列——这很可能不是您想要的。即使你让 for 循环做你想做的事,它也会找到所有匹配项,而不仅仅是第一个。loop / recur 示例在第一次匹配时停止。

于 2012-05-03T23:01:49.093 回答
0

我的看法,使用clojure.contrib.seq find-first,索引:

(defn ret-match-row [rows val col-idx]
(第一的
(find-first #(= val (nth (second %) col-idx))
(索引行))))
于 2012-05-08T06:50:34.797 回答