我的问题是如何捕获匹配发生的向量行的索引?在下面的代码中,我做错了什么?
我有一个向量载体
(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,我应该看到(第一个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
答案 0 :(得分: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)
答案 1 :(得分: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)
答案 2 :(得分: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的不变性 - (incn)实际上并没有修改rn。 loop / recur解决方案也使用inc,但它将inc的结果传递给循环的下一次迭代。
Clojure for(list comprehension)表单也将遍历序列中的所有值,从而产生一个新序列 - 这很可能不是你想要的。即使你让for循环做你想要的,它也会找到所有的匹配,而不仅仅是第一个。循环/重复示例在第一场比赛时停止。
答案 3 :(得分:0)
我的看法,使用 clojure.contrib.seq find-first,indexed:
(defn ret-match-row [rows val col-idx]
(first
(find-first #(= val (nth (second %) col-idx))
(indexed rows))))