2017-04-04 29 views
1

顯然get-in不適用於'()列表,因爲它們不是關聯數據結構。這對於API和從大型列表的性能角度來說是有意義的。從我作爲用戶的角度來看,仍然可以使用這個函數來探索repl中的一些小測試數據。例如,我希望能夠:進入列表

(-> '({:a ("zero" 0)} {:a ("one" 1)} {:a ("two" 2)}) 
    (get-in [1 :a 0])) 

=> "one" 

是否有一些其他功能以這種方式工作?有沒有其他的方式來實現這種行爲,而不涉及將所有列表轉換爲(比如說)向量?

+0

順便說一句,SO不會讓我發佈這個問題,直到我在標題中的'get-in'中取代G。這似乎是一個不好的功能...... – user12341234

回答

3

這確實你問:

(defn get-nth-in [init ks] 
    (reduce 
    (fn [a k] 
     (if (associative? a) 
     (get a k) 
     (nth a k))) 
    init 
    ks)) 

例如,

(-> '({:a "zero"} {:a "one"} {:a "two"}) 
    (get-nth-in [1 :a])) 
;"one" 

(-> '({:a ("zero" 0)} {:a ("one" 1)} {:a ("two" 2)}) 
    (get-nth-in [1 :a 0])) 
;"one" 

個額外'是你已經得到擴展到(quote ...)

(-> '({:a '("zero" 0)} {:a '("one" 1)} {:a '("two" 2)}) 
    (get-nth-in [1 :a 0])) 
;quote 

不是你想要的,我想。

+0

Yup!我搞砸了這個例子,但這個功能正是我所期待的。謝謝! – user12341234

-1

進入的第一個參數應該是一張地圖。

你必須弄清楚你的序列的功能,使用最後一個,第一個,過濾器或一些例如獲取該元素第一

例如,你可以使用(:a (last data))

+0

第一個參數不需要映射,例如它可以是一個向量。我更新了我的問題以打破您的示例解決方案。 – user12341234

+0

這就是爲什麼我說你必須弄清楚你的序列的特徵,如果你願意使用索引,像這樣做'( - >(vec'({:a「zero」} {:a「one」}) )) (get-in [1:a]))'然而,在向量中使用索引並不是一個完美的方法 – tony

2

A post just yesterday在懶惰列表和懶惰地圖(來自clojure/data.xml)方面存在問題。一個答案是使用該功能與普通的載體只需更換懶位&地圖:由於計算出的數據結構只使用矢量&地圖

(defn unlazy 
    [coll] 
    (let [unlazy-item (fn [item] 
         (cond 
         (sequential? item) (vec item) 
         (map? item) (into {} item) 
         :else item)) 
     result (postwalk unlazy-item coll) 
    ] 
    result)) 

,它爲你的榜樣與get-in

(let [l2 '({:a ("zero" 0)} {:a ("one" 1)} {:a ("two" 2)}) 
     e2 (unlazy l2) ] 
     (is= l2 e2) 
     (is= "one" (get-in e2 [1 :a 0] l2)) 
    ) 

你可以找到unlazy功能in the Tupelo library.

+0

在我的特殊情況下,unlazying非常耗時,所以對我來說,接受的答案仍然是可取的,但這仍然是一個很好的功能,可以保持在一個下雨天。 – user12341234