iT邦幫忙

2022 iThome 鐵人賽

DAY 7
0

Sets

Sets是一組不重複值的集合,

例如本期樂透號碼就很適合用Set存放,因為數字不可能重複:

Javascript Clojurescript
new Set(22, 4, 16, 8, 10, 2) #{22 4 16 8 10 2}

移除重複的值: set & conj

set好用的地方之一,把Vector裡的值轉成Sets也順便處理重複資料,乾淨溜溜~

=> (set ["h" "a" "p" "p" "y" "b" "i" "r" "t" "h" "d" "a" "y"])

#{"d" "p" "a" "t" "i" "b" "r" "y" "h"}

把keyword加進set裡,用conj也順便處理重複資料

例如I love you裡~

=> (conj #{:i :l :o :v :e } :y :o :u)

#{:y :v :o :e :l :i :u}

重複的ov就被移除囉

來試試看set與各種資料結構搭配

set 與 vectors

tutorial.core=> (set [8 8 2 5 2 5 2])
#{2 5 8}

set 與 lists

tutorial.core=> (set '(8 8 2 5 2 5 2))
#{2 5 8}

注意:List前面一定要有'的符號,然會壞掉
出現了ClassCastException

'(8 8 2 5 2 5 2) 意思是把lists存起來,回傳原本的list

tutorial.core=> (set (8 8 2 5 2 5 2))
Execution error (ClassCastException) at tutorial.core/eval2085 (form-init2678990013733270315.clj:1).
class java.lang.Long cannot be cast to class clojure.lang.IFn (java.lang.Long is in module java.base of loader 'bootstrap'; clojure.lang.IFn is in unnamed module of loader 'app')

clojure大大指點:

沒有 quote 的 expression 之所以噴錯,問題出於 list 的獨特的 interpretation

有空要來好好探究一下原因

hash-set來設定Set

set裡面也可以放不同的data structure們來大亂鬥,

例如之前學過的 string, keywords

(hash-set :hello "你好嗎" "衷心感謝" "期待再相逢" )

=> #{"期待再相逢" :hello "衷心感謝" "你好嗎"}

或是更簡便的方式:直接把elements寫在#{}裡面


#{:hello "你好" :Iam 18 "years olds"}

=> #{"你好" :Iam :hello "years olds" 18}

補充:

hash-set 除了是 Clojure 的四大 data structure 之一,它也是一個 function,也是可以「呼叫」的。

但return順序好像有點亂掉XD

既然說到了順序,
就來看看collections API
試試API上的sorted-set會產生什麼樣的效果

sorted-set

把剛剛的你好我今年18歲例子丟給 sorted-set後發現會throw error


(sorted-set :hello "你好" :Iam 18 "years olds")

Execution error (ClassCastException) at java.lang.String/compareTo (String.java:134).

class clojure.lang.Keyword cannot be cast to class java.lang.String (clojure.lang.Keyword is in unnamed module of loader 'app'; java.lang.String is in module java.base of loader 'bootstrap')

原因是 unable to implement java.lang.String.compareTocompare不能比較不同的type。

如果全部改為keywords就可以執行。

(sorted-set :hello :你好 :Iam :18 :years :olds)
=> #{:18 :Iam :hello :olds :years :你好}

如果真的要比較的話,可以使用sorted-map,但要在不同型態的元素前面加上keyword

補充比較:sorted-map

參考https://clojure.org/guides/comparators,

稍稍改一下例子,讓執行結果可以按照keyword的alphabetical排序

(sorted-map :hello :你好嗎 :thanks 9527 :see-you "期待再相逢" )
=> {:hello :你好嗎, :see-you "期待再相逢", :thanks 9527}

結論

今天看了兩個ClassCastException的Execution error ,在做collection轉換時偶爾也會遇到一些error,這時候靜下心來讀error的提示,並且注意回去對照API文件上的使用說明,通常都可以成功排除問題。

更多collections API小抄可以看這裡!

延伸思考

記下可能需要了解,但還未涵蓋在本文內容的項目:

  • set(把任何其他 collection 轉換成為目標collection type)有別於hash-set,就像之後預計在Day09提的vec有別於vector
  • hash-set 接受多個parameters的collection constructor
  • hash-set 除了是 Clojure系列文提到的四大data structure之一,它也是一個function,在實務上非常方便。

Reference:

Quickref for Clojure Core


上一篇
[Day06] Clojure data structure之collection系列(3) Maps
下一篇
[Day08] Clojure Functional Programming與資料操作(1) - map
系列文
後端Developer實戰ClojureScript: Reagent與前端框架 Reframe30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言