Ruby 好用的 Set 與應用

紅寶鐵軌客
Join to follow...
Follow/Unfollow Writer: 紅寶鐵軌客
By following, you’ll receive notifications when this author publishes new articles.
Don't wait! Sign up to follow this writer.
WriterShelf is a privacy-oriented writing platform. Unleash the power of your voice. It's free!
Sign up. Join WriterShelf now! Already a member. Login to WriterShelf.
寫程式中、折磨中、享受中 ......
963   0  
·
2019/03/26
·
3 mins read


Ruby 中被遺忘的珍珠:Set(集合)

很多人可能都忘了 Ruby 中有內建很好用的「Set(集合)」程式庫,忘記它的理由可能只是它因為是在標準程式庫中,使用時必須要 require 進來,可是在 Rails 中,直接用就可以了。

Ruby 的 Set(集合)非常好用,特別是與 Array 有幾乎相同的運算方式,Set(集合)是使用 Hash 來儲存,所以很多 hash 的運用也通用,Set(集合)與 Array 有以下兩個最重要最大的不同:

  1. Set(集合)會自動移除重複的 elements 元素
  2. Set(集合)沒有排列順序

在很多情況下,適當的使用 Set(集合)與 Array (陣列)可以大幅的減少開發的難度,兩者的混用,更是一個強強結合。

我們先來看一下 Set(集合)的基本運算,對應到離散數學上的集合運算:

> require 'set'

# 聯集 OR
> Set[1,2,3] | Set[3,4,5]
=> #<Set: {1, 2, 3, 4, 5}>

# 交集 AND
> Set[1,2,3] & Set[2,3,4,5]
=> #<Set: {2, 3}>

# 互斥或 XOR (觀察到 Set 沒有排列順序了嗎!)
> Set[1,2,3] ^ Set[3,4,5]
=> #<Set: {4, 5, 1, 2}>

# 加 +
> Set[1,2,3,4] + Set[3,4,5]
=> #<Set: {1, 2, 3, 4, 5}>

# 減 -
> Set[1,2,3,4] - Set[3,4,5]
=> #<Set: {1, 2}>

# 只儲存不同的元素
> Set[1,2,3,3,2,1]
=> #<Set: {1, 2, 3}>

# 判斷相等
> Set[1,2,3] == Set[3,1,2]
=> true

# 判斷不等
> Set[1,2,3] != Set[3,1,2]
=> false

# 子集 subset
>Set[1,2,3] <( Set[3,1,2,4])
=> true
> Set[1,2,3] <( Set[3,1,2])
=> false

# 真子集 proper subset
> Set[1,2,3] <=( Set[3,1,2,4])
=> true
> Set[1,2,3] <=( Set[3,1])
=> false

# 也可以用 Enumerable
Set[2,4,8,16].each {|el| puts el}
#=> 2
#   4
#   8
#   16 

這只是列出了一小部分,更多就請看一下文件了。

應用:

實務上,我們有很多地方可以用到,特別是如果結合 Array 跟 Set,例如:我們要一個沒有重複的 elements 元素的 Array,要移除相同的元素,可能不是那麼簡單,現在,我們只要用 set,輕輕鬆鬆就可以辦到!如下:

Array 移除相同的元素
# 在 Array 中移除相同的元素
> a = [1,2,3,3,2,1]
=> [1, 2, 3, 3, 2, 1]
> a.to_set.to_a
=> [1, 2, 3]

用 Set 跟 Array 來玩字串,也很有趣,有想過如何找出一段文字中,所有不同的單字嗎?轉一轉就好了! 

一段文字中,找出所有不同的單字
# 找出字串中不同的字
s="Set implements a collection of unordered values with no duplicates. This is a hybrid of Array's intuitive inter-operation facilities and Hash's fast lookup."

> s.gsub(".","").split(' ').to_set.to_a.reject(&:empty?)
=> ["Set", "implements", "a", "collection", "of", "unordered", "values", "with", "no", "duplicates", "This", "is", "hybrid", "Array's", "intuitive", "inter-operation", "facilities", "and", "Hash's", "fast", "lookup"]

> s.gsub(".","").split(' ').to_set.to_a.reject(&:empty?).join(", ")
=> "Set, implements, a, collection, of, unordered, values, with, no, duplicates, This, is, hybrid, Array's, intuitive, inter-operation, facilities, and, Hash's, fast, lookup"

是不是很簡單又有趣!我很喜歡 Set(集合),我以前幾乎都忘了它的存在,它的沒有重複元素的特性,在很多運用上,可以簡化很多開發難度。

有要注意的點嗎?

當然使用上還是有要注意的,我目前想到最大的問題就是,因爲 Set(集合)沒有固定排列順序,這是跟 Array 最大的不同點,所以使用上要稍微小心一點,很容易跟 Set 跟 Array 混淆,不過,如果有學過離散數學,這問題就不大了。  我前幾天還在跟人聊天,說上課時學了一學期的離散數學,好像都沒用到過,沒想到,馬上就用到了,真是墨菲定律啊。

備註,及一些好用的參考:

  1. 內容有部分來自:When Is a Ruby Set Better Than a Ruby Array?


WriterShelf™ is a unique multiple pen name blogging and forum platform. Protect relationships and your privacy. Take your writing in new directions. ** Join WriterShelf**
WriterShelf™ is an open writing platform. The views, information and opinions in this article are those of the author.


Article info

This article is part of:
Categories:
Tags:
Date:
Published: 2019/03/26 - Updated: 2019/03/26
Total: 894 words


Share this article:
About the Author

很久以前就是個「寫程式的」,其實,什麼程式都不熟⋯⋯
就,這會一點點,那會一點點⋯⋯




Join the discussion now!
Don't wait! Sign up to join the discussion.
WriterShelf is a privacy-oriented writing platform. Unleash the power of your voice. It's free!
Sign up. Join WriterShelf now! Already a member. Login to WriterShelf.