返回元素Clojure的位置

时间:2015-11-04 21:53:44

标签: recursion clojure functional-programming lisp iteration

我正在努力找到解决我目前遇到的问题的方法,我已经尝试并试图让这个工作但无济于事。我正在尝试扫描包含数据的列表,然后返回数据的位置(如果找到)。

例如,如果我跑了这个:

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

我试图做的是遍历列表,直到它达到一个值并将其添加到空列表中,一旦它循环返回空列表。

4 个答案:

答案 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)))))

这与您的程序采用相同的一般方法,但以更惯用的方式做一些事情。主要是,它通过列表在另一个方向上使用firstrest,使用内部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-letif内包含let
  • 解构表单[y & ys]包含对firstrest的调用。
  • if表单向下推入recur可避免重复。