我正在努力找到解决我目前遇到的问题的方法,我已经尝试并试图让这个工作但无济于事。我正在尝试扫描包含数据的列表,然后返回数据的位置(如果找到)。
例如,如果我跑了这个:
(ind 'p '(l m n o p o p))
然后我会得到一个......的返回值。
==> 4 6
因为它已经在那些位置找到了数据。
我已经接近了,我想我以前想用这个解决方案,但我无法让它运行。任何人都可以帮我弄清楚我的功能是什么?据我所知它应该有效,但我无法弄清楚为什么它不是?
(defn ind
([choice list emptylist x]
(let [x (count list)])
(if (= (x) 0)
nil)
(if (= (first list) item)
(ind item (rest list) (cons x emptylist) (dec x))
(ind item (rest list) emptylist (dec x))
)
)
)
我试图做的是遍历列表,直到它达到一个值并将其添加到空列表中,一旦它循环返回空列表。
答案 0 :(得分:5)
我发现在Clojure中有一个名为keep-indexed
的内置函数。
所以你可以这样做:
(keep-indexed (fn [idx elm] (if (= 'p elm) idx)) '(l m n o p o p))
; return (4 6)
答案 1 :(得分:1)
因此,您的代码的主要问题是您多次使用item
而没有声明它。这使得defn
甚至不能成功定义函数。
这是该程序的工作副本
(defn ind [item item-list] ;;Only take the needed arguments
;;Declare the mutable variables here, so they don't escape into the signature
(loop [items item-list ;;remaining items
index 0 ;;current index
result '()] ;;current result
(if (empty? items) result ;;If nothing left, return our result
(if (= item (first items))
(recur (rest items) ;;If it matches, add to the result list and repeat
(inc index)
(cons index result))
(recur (rest items) ;;If it doesn't match, just repeat
(inc index)
result)))))
这与您的程序采用相同的一般方法,但以更惯用的方式做一些事情。主要是,它通过列表在另一个方向上使用first
和rest
,使用内部loop
,以便您只在函数中拥有所需的参数,并使用{ {1}}这样它就是尾递归。
答案 2 :(得分:0)
这是一个我认为更简单的解决方案:
(defn find-index
"Returns a seq of the indexes of the supplied collection."
[values target]
(let [indexes (range (count values))
val-idx-tuples (map vector values indexes)
found-tuples (filter #(= target (first %)) val-idx-tuples)
found-indexes (vec (map second found-tuples)) ]
found-indexes))
(println (find-index '(l m n o p o p) 'p ))
;=> [4 6]
答案 3 :(得分:0)
虽然我更喜欢@chanal's approach,但您可以按如下方式编写所需的功能:
(defn ind [x coll]
(loop [ans [], coll coll, n 0]
(if-let [[y & ys] (seq coll)]
(recur (if (= x y) (conj ans n) ans) ys (inc n))
ans)))
(ind 'p '(l m n o p o p))
;[4 6]
这使用了几个成语来简化:
if-let
在if
内包含let
。[y & ys]
包含对first
和rest
的调用。if
表单向下推入recur
可避免重复。