2015-11-04 114 views
1

我想找到一個解決方案,我目前面臨的問題,我試過並試圖讓這個工作,但無濟於事。我試圖掃描包含數據的列表,然後返回數據的位置(如果找到)。返回一個元素的位置Clojure

例如,如果我跑了這一點:

(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

我相信這是一個重複的http:// stackoverflow。COM /問題/ 4830900 /怎麼辦,我找到的最指數的-的項目-IN-A-矢量 –

回答

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在另一個方向上的列表工作,以便您只有函數中需要的參數,並使用recur,以便它是尾遞歸。

+0

我試圖實現這一點,但所有的返回是: () 我我輸入它像我這樣的原始功能相同的方式: (ind'p'(lmnopop)) 但它只是返回()?當我調用函數 –

+0

@BeanShares時我有什麼錯誤嗎?我的錯誤。我做了一個我忽略測試的最後一刻的變化。現在應該糾正。 – resueman

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] 
+0

你可以不使用索引。只要說'(let [val-idx-tuples(map vector values(range))...] ...)''。當任何集合用完時,map都會終止。你可以使用'map-indexed'而不是'map'來獲得類似的效果。我也會留下最後的'vec'。那麼整個事情就是懶惰的,所以客戶可以決定如何以及何時實現它。 – Thumbnail

5

我發現有Clojure中稱爲keep-indexed內置功能。

所以,你可以簡單地這樣做:

(keep-indexed (fn [idx elm] (if (= 'p elm) idx)) '(l m n o p o p)) 
; return (4 6) 
+0

建議你把它作爲所需要的函數:'(defn ind [x coll](keep-indexed(fn [idx elm](if(= x elm)idx))coll))' – Thumbnail

+0

哇,我從來沒有見過功能之前。 –

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]包括對firstrest的調用。
  • if表單向下壓入recur避免了重複。