1

I am trying to find a solution to a problem i am facing at the moment, i have tried and tried to get this working but to no avail. I am trying to scan a list containing data and then returning the position of the data if found.

For example if i ran this:

(ind 'p '(l m n o p o p))

Then i would get a return value of....

==>  4 6  

As it has found the data in those positions.

I have come close i think to what i want with this solution before, but i cannot get it to run. Can anyone help me figure out whats up with my function?? As far as i can see it should work, but i cant figure out why it isnt?

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

What i have tried to do is loop through the list until it hits a value and add it to the empty list and once it has looped through return the empty list.

Bean Shares
  • 49
  • 1
  • 6
  • I believe this is a duplicate http://stackoverflow.com/questions/4830900/how-do-i-find-the-index-of-an-item-in-a-vector – Ricardo Acuna Nov 06 '15 at 00:21

3 Answers3

5

I found that there is a built-in function called keep-indexed in Clojure.

So you can simply do this:

(keep-indexed (fn [idx elm] (if (= 'p elm) idx)) '(l m n o p o p))
; return (4 6)
resueman
  • 10,572
  • 10
  • 31
  • 45
chanal
  • 51
  • 1
0

Here is a solution which I think is a bit simpler:

(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]
Alan Thompson
  • 29,276
  • 6
  • 41
  • 48
  • You can do without `indexes`. Just say `(let [val-idx-tuples (map vector values (range)) ... ] ...)`. The `map` terminates when any of the collections runs out. You can get a similar effect using `map-indexed` instead of `map`. I'd also leave out the final `vec`. Then the whole thing is lazy, so the client can decide how and when to realise it. – Thumbnail Nov 05 '15 at 23:37
0

Though I prefer @chanal's approach, you can write the function you want as follows:

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

This uses several idioms to make it concise:

  • if-let comprises if inside let.
  • The destructuring form [y & ys] comprises calls to first and rest.
  • Pushing the if form down into the recur avoids repetition.
Community
  • 1
  • 1
Thumbnail
  • 13,293
  • 2
  • 29
  • 37