Ruby 札記 - Ruby 集合家族之雜湊(Hash)

GracKanil發表於2018-08-29

前言

說完陣列,就知道下一個肯定是雜湊,在 Objective-C 裡的體現是字典(NSDictionary)。為什麼這種集合很受歡迎呢?這要從雜湊演算法說起,簡單的說,hash 能以 O(1)的複雜度將內容對映到位置。Hash 演算法的原理和基礎概念,不乏好文,此處不贅述。後面可以專門複習梳理下。

建立雜湊

?> hash = {}
=> {}
>> hash['1'] = "one"
=> "one"
?> hash
=> {"1"=>"one"}
>>
?> h = Hash.new
=> {}
>> h['2'] = "two"
=> "two"
>> h
=> {"2"=>"two"}
複製程式碼

可以用 => 初始化 hash,可以叫它雜湊火箭?(調皮)

?> h = {
?> '1' => "one",
?> '2' => "two"
>> }
=> {"1"=>"one", "2"=>"two"}
>> h
=> {"1"=>"one", "2"=>"two"}
複製程式碼

如果取沒有 key 的值,返回 nil。當然這取決於你構造時有沒有傳預設值。

?> h["3"]
=> nil

?> h = Hash.new(0)
=> {}
>> h['4']
=> 0
複製程式碼

刪除,簡單的置值為 nil 不能刪除。可以使用#delete方法

?> h = {'1' => "one", '2' => "two"}
=> {"1"=>"one", "2"=>"two"}
>> h.size
=> 2
>> h['1'] = nil
=> nil
>> h.size
=> 2
>> h
=> {"1"=>nil, "2"=>"two"}
>> h.delete('1')
=> nil
>> h.size
=> 1
>> h
=> {"2"=>"two"}
複製程式碼

也可以使用一些表示作為鍵值,也可以不使用 => 建立雜湊(使用冒號,這和 Objective-C 很相似)

?> h = {:one => 1, :two => 2}
=> {:one=>1, :two=>2}
>> h
=> {:one=>1, :two=>2}
>>
?> h = {one: 1, two: 2}
=> {:one=>1, :two=>2}
>> h
=> {:one=>1, :two=>2}
複製程式碼

常用方法

  • 基礎方法
?> a = {"one" => "grac", "two" => "kanil"}
=> {"one"=>"grac", "two"=>"kanil"}
>>
?> a.keys
=> ["one", "two"]
>> a.values
=> ["grac", "kanil"]
>> a.length
=> 2
>> a.size
=> 2
複製程式碼
  • has_key?
?> a = {"one" => "grac", "two" => "kanil"}
=> {"one"=>"grac", "two"=>"kanil"}
>> a.has_key? "one"
=> true
複製程式碼
  • select
?> a = {"one" => "grac", "two" => "kanil"}
=> {"one"=>"grac", "two"=>"kanil"}
?> a.select { |k, v| k == "one"}
=> {"one"=>"grac"}
>>
?> a.select { |k, v| k == "one" || k == "two"}
=> {"one"=>"grac", "two"=>"kanil"}
複製程式碼
  • to_a
?> a = {"one" => "grac", "two" => "kanil"}
=> {"one"=>"grac", "two"=>"kanil"}
?> a.to_a
=> [["one", "grac"], ["two", "kanil"]]
複製程式碼
  • 合併兩個 Hash
>> { "one" => "grac" }.merge({ "two" => "kanil" })
=> {"one"=>"grac", "two"=>"kanil"}
複製程式碼
  • fetch 和使用 [] 一樣獲取陣列 value,但是如果沒有會 raise 錯誤
?> a = {"one" => "grac", "two" => "kanil"}
=> {"one"=>"grac", "two"=>"kanil"}
>> a["three"]
=> nil
>> a.fetch("two")
=> "kanil"
>> a.fetch("three")
KeyError: key not found: "three"
	from (irb):7:in `fetch'
	from (irb):7
    ...
複製程式碼

函式關鍵字引數傳遞

Ruby 不支援關鍵字引數,但可以使用 Hash 模擬出來

?> class Article
>>   attr_accessor :name, :author, :price
>>
?>   def initialize(params = {})
>>     @name = params[:name]
>>     @author = params[:author]
>>     @price = params[:price]
>>   end
>> end
=> :initialize
>> a = Article.new(name: "霧都", author: "tom", price: 12.5)
=> #<Article:0x007ffc2189f970 @name="霧都", @author="tom", @price=12.5>
>>
?> a.name
=> "霧都"
複製程式碼

迭代

和陣列很類似

?> hash = {name: "霧都", author: "tom", price: 12.5}
=> {:name=>"霧都", :author=>"tom", :price=>12.5}
>>
?> hash.each {|key, value| puts "#{key} => #{value}"}
name => 霧都
author => tom
price => 12.5
=> {:name=>"霧都", :author=>"tom", :price=>12.5}
複製程式碼

相關文章