clojure 新手指南(14):Hash-Maps ,Array-Maps & Sorted...

hash-map

建立

在clojure中,哈希表是最通用的一種Map,和java中的HashMap同樣,它們在處理大量數據方面效率很是高,可是不保證順序。咱們可使用函數hash-map來建立哈希表: java

=>(hash-map :truck "Toyota" :car "Subaru" :plane "de Havilland")
{:plane "de Havilland", :truck "Toyota", :car "Subaru"}

=>(class (hash-map :truck "Toyota" :car "Subaru" :plane "de Havilland"))
clojure.lang.PersistentHashMap

在clojure中,全部的類型對象均可以做爲map的鍵,甚至是函數對象也能夠。可是咱們推薦使用關鍵字類型(以冒號開頭)做爲map的鍵,由於關鍵字做爲鍵時哈希表性能最好。建立哈希表時不必定非得用hash-map 函數,下面就是一個更簡便的方式: 編程

;;直接使用{}來建立哈希表
=>{:truck "Toyota" :car "Subaru" :plane "de Havilland"}
{:truck "Toyota", :car "Subaru", :plane "de Havilland"}
不過,用上面這種方式,若是傳入的鍵值對少於9個,它實際上建立的是ArrayMap而不是HashMap:

=>(class {:truck "Toyota" :car "Subaru" :plane "de Havilland"})
clojure.lang.PersistentArrayMap
一旦你把它綁定到一個變量上,它自動就轉換成了hashMap:

=> (def map {test: 1})
#'user/map

=> (class map)
clojure.lang.PersistentHashMap

ArrayMap 和 HashMap這種轉換,看起來很詭異。可是不要擔憂,由於大部分狀況下,這都不會引發問題。我見過的全部函數對這兩種map的操做都是同樣的,沒有任何區別。 json

建立map時,若是你想讓鍵值對之間的分隔更清晰,可使用逗號分隔符: 函數式編程

;;使用hash-map函數
=> (hash-map :key1 1 , :key2 2)
{:key2 2, :key1 1}

;;直接建立
=>{:key1 1 , :key2 2}
{:key2 2, :key1 1}

咱們再來看看和map相關的操做 函數


讀取

;;若是是map的鍵是關鍵字類型,關鍵字直接能夠當作函數使用

=> (def m {:key1 1, :key2 2})
{:key1 1, :key2 2}

;;獲取:key1對應的值
=> (:key1 m)
1

;;map自己也能夠用於取值,這種適應於任意類型的key
=> (m :key1)
1

一種更好的方式是使用get函數,由於能夠設置缺省值。(get 也能夠用於向量,把key變成索引值便可) 性能

=> (def m {:key1 1 :key2 :2})

;;獲取 :key1對應的值
=> (get m :key1)
1

;;若是 :key3不存在,返回缺省值
=> (get m :key3 "default")
"default"

咱們可使用get-in 獲取嵌套map的值 spa

;;建立嵌套map
user=> (def m {:username "sally"
               :profile {:name "Sally Clojurian"
                         :address {:city "Austin" :state "TX"}}})
'user/m

user=> (get-in m [:profile :name])
"Sally Clojurian"

user=> (get-in m [:profile :address :city])
"Austin"

user=> (get-in m [:profile :address :zip-code])
nil

;;若是鍵不存在,能夠設置默認值 
user=> (get-in m [:profile :address :zip-code] "no zip code!")
"no zip code!"

我敢說這是json好麼!!!(get-in 函數可不僅是用於map,向量也可使用get-in操做) code


增長/修改

;;沒則增長,有則修改 
=>(conj {:name "qh" :age 20} {:age 30} {:gender 'male})
{:gender mail, :age 30, :name "qh"}

;;沒則增長,有則修改
=>(merge {:name "qh" :age 20} {:age 30} {:gender 'male})
{:gender mail, :age 30, :name "qh"}

;;assoc是操做map和對應的元素,上面兩個操做的是多個map,注意區別
=>(assoc {:name "qh" :age 20} :age 30 :gender 'male)
{:gender mail, :age 30, :name "qh"}


刪除

;;刪除:name對應的鍵值對
=>(dissoc {:name "qh" :age 30} :name)
{:age 30}

;;給m綁定一個map
=> (def m {:name "qh" :age 30})
#'user/m

;;執行刪除操做
=>(dissoc m :name)
{:age 30}

;;m沒有變化
=>m
{:name "qh" :age 30}
咱們的刪除操做只是返回一個新的map,並不會對原有的map形成影響。這點要注意。這也是函數式編程中強調的"消除反作用"。以前的添加和修改都是如此。


獲取全部的key

;;使用keys函數
=> (keys {:name "clo" :age 30})
(:name :age)


獲取全部的value

;;使用vals函數獲取全部value
=> (vals {:name "clo" , :age 30})
("clo" 30)


Sorted Maps

若是咱們想要建立一個有序的map(按照key的天然順序),可使用sorted-map函數來建立一個有序map。 對象

user=> (def sm (sorted-map :c 1 :b 2 :f 3 :a 3))
#'user/sm
user=> sm
{:a 3, :b 2, :c 1, :f 3}
有序map增刪改查操做和上面同樣。
相關文章
相關標籤/搜索