Ruby Study 5 : Hash, Martix, Vector and Set class

简介:
Hash class
1. introduce
前面一篇讲了一下Array, 其实Hash 和Array还是比较类似的, 只不过Hash的每个元素是由key和value组成的.
我们来看看创建Hash的几种方法.
h1 = {1=>'d', 2=>'c', 3=>'b', 4=>'a'}
h2 = Hash.new()
h3 = Hash.new("default value")

这里分别创建了3个Hash对象, h1 有4个元素. h2和h3都没有元素, 只不过h3设置了value的默认值.
例如 :
p(h2["this is a key"])  # h2由于没有默认值, 所以对应这个key的value值是nil.
p(h3["this is a key"])  # h3则返回默认值.

输出 : 
nil
"default value"

Hash和Array的另一个不同之处是, Hash的key是唯一的, 而Array中允许重复元素. 
例如 :
a1 = [1,1,1,1,1]
h1 = {1=>'d', 2=>'c', 3=>'b', 4=>'a'}
h1[1] = 'f'  # 这个操作是修改key=1的value. 而不是增加一个1=>'f'的元素, 因为Hash不允许重复KEY出现
p(a1)
p(h1)

执行结果 : 
[1, 1, 1, 1, 1]
{1=>"f", 2=>"c", 3=>"b", 4=>"a"}

添加Hash元素 :
h1 = Hash.new()
h1[1] = 'd'
h1[2] = 'c'
h1[3] = 'b'
h1[4] = 'a'
p h1

执行结果
{1=>"d", 2=>"c", 3=>"b", 4=>"a"}

Hash的key和value允许使用任意类型的数据, 如Symbol, String, Fixnum, 包括自定义类的对象以及nil.
h1 = Hash.new()
class Myclass
end
m1 = Myclass.new()

h1[m1] = nil
h1[1] = 'a'
h1['a'] = :thisasymbol
p h1

执行结果 :
{#<Myclass:0x1dc1108>=>nil, 1=>"a", "a"=>:thisasymbol}

2. Create Hash object
这个上面已经讲过了.

3. Indexing into a Hash
这个上面也讲过了, 需要提醒的是, 使用了默认值的Hash, 当查找一个不存在的key时返回的是默认值, 默认值可以通过default=方法修改.
h1 = Hash.new('default value 1')
p h1[1]
h1.default = 'new default value'
p h1[1]
p h1.default

执行结果 :
"default value 1"
"new default value"
"new default value"


4. Copy a Hash
拷贝一个Hash 和拷贝Array, String等类型一样, 需要注意如果通过赋值的话实际上只是拷贝了值的reference. 而不是新建一个对象.
例如 :
h1 = {1=>'digoal',2=>'francs'}
h2 = h1  # 这是个reference的拷贝
h3 = h1.clone  # 使用clone方法才是创建一个新的对象
h2[3] = 'hank'
h3[4] = 'david'
p h1.object_id
p h2.object_id
p h3.object_id
p h1
p h2
p h3

执行结果 : 
15861696
15861696
15861684
{1=>"digoal", 2=>"francs", 3=>"hank"}
{1=>"digoal", 2=>"francs", 3=>"hank"}
{1=>"digoal", 2=>"francs", 4=>"david"}

5. Hash Order
注意在1.8 和 1.9的版本中有一定的区别, 1.8中Hash对象的顺序是按照key排序来存储的.
1.9则是插入的顺序. 所以1.9在插入速度上应该是快于1.8的. 包括存储的效率也应该比1.8高.
来看个例子 :
h1 = Hash.new()
h1[4] = 'a'
h1[3] = 'b'
h1[2] = 'c'
h1[1] = 'd'
p h1

1.9的执行结果 : 
{4=>"a", 3=>"b", 2=>"c", 1=>"d"}

1.8的执行结果 :
{1=>"d", 2=>"c", 3=>"b", 4=>"a"}

6. Sorting a Hash
给Hash排序, 实际上是先把Hash转换成2维的Array再排序, 就像这样的[[key1,value1], [key2,value2], [key3,value3]...]
因为转换后key在前, value在后,  所以排序是按照key来排的.
所以我们可以通过给 sort 方法传递一个块进去, 选择按照key或者value来排序.
例如 :
h1 = {1=>'d', 2=>'c', 3=>'b', 4=>'a'}
p( h1.sort )  # 这种排序方法和接下来的一致.
p( h1.sort {
  |x,y|
  x[0].to_s <=> y[0].to_s
} )
p( h1.sort { # 这种排序则是按value来排的.
  |x,y|
  x[1] <=> y[1]
} )

执行结果 :
[[1, "d"], [2, "c"], [3, "b"], [4, "a"]]
[[1, "d"], [2, "c"], [3, "b"], [4, "a"]]
[[4, "a"], [3, "b"], [2, "c"], [1, "d"]]

# 注意到sort后返回的是Array类型, 也就是前面所讲.
如果你觉得每次要这样写不爽, 我们可以定义一个给Hash排序的方法 .
def hash_sort_byvalue (ahash)
  return ahash.sort {
    |x,y|
    x[1].to_s <=> y[1].to_s
  }
end

h1 = {1=>'d', 2=>'c', 3=>'b', 4=>'a'}
p( hash_sort_byvalue(h1) )

执行结果 :
[[4, "a"], [3, "b"], [2, "c"], [1, "d"]]


7. Hash Methods
来看看Hash对象有多少方法好调用?
h1 = Hash.new()
print(h1.methods.sort)

执行结果 :
[:!, :!=, :!~, :<=>, :==, :===, :=~, :[], :[]=, :__id__, :__send__, :all?, :any?, :assoc, :chunk, :class, :clear, :clone, :collect, :collect_concat, :compare_by_identity, :compare_by_identity?, :count, :cycle, :default, :default=, :default_proc, :default_proc=, :define_singleton_method, :delete, :delete_if, :detect, :display, :drop, :drop_while, :dup, :each, :each_cons, :each_entry, :each_key, :each_pair, :each_slice, :each_value, :each_with_index, :each_with_object, :empty?, :entries, :enum_for, :eql?, :equal?, :extend, :fetch, :find, :find_all, :find_index, :first, :flat_map, :flatten, :freeze, :frozen?, :grep, :group_by, :has_key?, :has_value?, :hash, :include?, :index, :initialize_clone, :initialize_dup, :inject, :inspect, :instance_eval, :instance_exec, :instance_of?, :instance_variable_defined?, :instance_variable_get, :instance_variable_set, :instance_variables, :invert, :is_a?, :keep_if, :key, :key?, :keys, :kind_of?, :length, :map, :max, :max_by, :member?, :merge, :merge!, :method, :methods, :min, :min_by, :minmax, :minmax_by, :nil?, :none?, :object_id, :one?, :partition, :private_methods, :protected_methods, :public_method, :public_methods, :public_send, :rassoc, :reduce, :rehash, :reject, :reject!, :replace, :respond_to?, :respond_to_missing?, :reverse_each, :select, :select!, :send, :shift, :singleton_class, :singleton_methods, :size, :slice_before, :sort, :sort_by, :store, :taint, :tainted?, :take, :take_while, :tap, :to_a, :to_enum, :to_hash, :to_s, :trust, :untaint, :untrust, :untrusted?, :update, :value?, :values, :values_at, :zip]

估计已经看到很多熟悉的了吧 . 下面来测试几个 : 
h1 = {
    'room1'=>'The Treasure Room',
    'room2'=>'The Throne Room',
    'loc1'=>'A Forest Glade',
    'loc2'=>'A Mountain Stream' 
    }
    
h2 = {1=>'one', 2=>'two', 3=> 'three'}
h1['room1'] = 'You have wandered into a dark room'
h1.delete('loc2')
p(h1)
#=> {"room1"=>"You have wandered into a dark room",
#=> "room2"=>"The Throne Room", 
#=> "loc1"=>"A Forest Glade"}
p(h1.has_key?('loc2')) #=> false
p(h2.has_value?("two")) #=>true
p(h2.invert)         #=> {"one"=>1, "two"=>2, "three"=>3}
p(h2.keys)            #=>[1, 2, 3]
p(h2.values)        #=>["one", "two", "three"]

执行结果  :
{"room1"=>"You have wandered into a dark room", "room2"=>"The Throne Room", "loc1"=>"A Forest Glade"}
false
true
{"one"=>1, "two"=>2, "three"=>3}
[1, 2, 3]
["one", "two", "three"]

其他的用法可以参考API.

8. Convert Hash to Array
h1 = {
    'room1'=>'The Treasure Room',
    'room2'=>'The Throne Room',
    'loc1'=>'A Forest Glade',
    'loc2'=>'A Mountain Stream' 
    }
p h1.to_a
p h1.keys
p h1.values

输出结果 :
[["room1", "The Treasure Room"], ["room2", "The Throne Room"], ["loc1", "A Forest Glade"], ["loc2", "A Mountain Stream"]]
["room1", "room2", "loc1", "loc2"]
["The Treasure Room", "The Throne Room", "A Forest Glade", "A Mountain Stream"]

其他例子 : 
h1 = {'key1'=>'val1', 'key2'=>'val2', 'key3'=>'val3', 'key4'=>'val4'}
h2 = {'key1'=>'val1', 'KEY_TWO'=>'val2', 'key3'=>'VALUE_3', 'key4'=>'val4'}
p( h1.keys & h2.keys )             # set intersection (keys)
#=> ["key1", "key3", "key4"]
p( h1.values & h2.values )        # set intersection (values)
#=> ["val1", "val2", "val4"]    
p( h1.keys+h2.keys )            # concatenation
#=> [ "key1", "key2", "key3", "key4", "key1", "key3", "key4", "KEY_TWO"]
p( h1.values-h2.values )            # difference
#=> ["val3"]
p( (h1.keys << h2.keys)  ) # append
#=> ["key1", "key2", "key3", "key4", ["key1", "key3", "key4", "KEY_TWO"]]
p( (h1.keys << h2.keys).flatten.reverse  ) # 'un-nest' arrays and reverse
#=> ["KEY_TWO", "key4", "key3", "key1", "key4", "key3", "key2", "key1"]

Matrix and Vector class
1. introduce
Matrix和Vector一般用于数学运算, 下面是一个例子 : 
使用Vector和Matrix类时需要包含Matrix模块.
require "Matrix"    # This is essential!
m1 = Matrix[ [1,2,3,4],
            [5,6,7,8],
            [9,10,11,12],
            [13,14,15,16]  ]
m2 = Matrix[ [10,20,30,40],
            [50,60,70,80],
            [90,100,110,120],
            [130,140,150,160]  ]
m3 = m1+m2
p(m3)

执行结果 :
Matrix[[11, 22, 33, 44], [55, 66, 77, 88], [99, 110, 121, 132], [143, 154, 165, 176]]

如果把Matrix理解为一个阵列, Vector可以理解为整列里的行.
下面看看如何把Vector类型转换成Matrix类型 : 
require "Matrix"
v1 = Vector[1,2,3,4,5]
v2 = Vector[6,7,8,9,10]
m1 = Matrix.columns([v1,v2]) # 按列组织成Matrix
p( m1 )
m2 = Matrix.rows([v1,v2])  # 按行组装成Matrix
p( m2 )

执行结果 : 
Matrix[[1, 6], [2, 7], [3, 8], [4, 9], [5, 10]]
Matrix[[1, 2, 3, 4, 5], [6, 7, 8, 9, 10]]


Set class
1. introduce
Set存储的是无序的无重复值的数组. 与Array不同之处就是它存储的值没有重复的.
require "Set"
s1 = Set.new([nil,nil,1,1,2,2,3,4,5,0,0])
p s1

执行结果 :
#<Set: {nil, 1, 2, 3, 4, 5, 0}>

它的方法和Array类似, 如下 : 
[:!, :!=, :!~, :&, :+, :-, :<<, :<=>, :==, :===, :=~, :^, :__id__, :__send__, :add, :add?, :all?, :any?, :chunk, :class, :classify, :clear, :clone, :collect, :collect!, :collect_concat, :count, :cycle, :define_singleton_method, :delete, :delete?, :delete_if, :detect, :difference, :display, :divide, :drop, :drop_while, :dup, :each, :each_cons, :each_entry, :each_slice, :each_with_index, :each_with_object, :empty?, :entries, :enum_for, :eql?, :equal?, :extend, :find, :find_all, :find_index, :first, :flat_map, :flatten, :flatten!, :flatten_merge, :freeze, :frozen?, :grep, :group_by, :hash, :include?, :initialize_clone, :initialize_dup, :inject, :inspect, :instance_eval, :instance_exec, :instance_of?, :instance_variable_defined?, :instance_variable_get, :instance_variable_set, :instance_variables, :intersection, :is_a?, :keep_if, :kind_of?, :length, :map, :map!, :max, :max_by, :member?, :merge, :method, :methods, :min, :min_by, :minmax, :minmax_by, :nil?, :none?, :object_id, :one?, :partition, :pretty_print, :pretty_print_cycle, :private_methods, :proper_subset?, :proper_superset?, :protected_methods, :public_method, :public_methods, :public_send, :reduce, :reject, :reject!, :replace, :respond_to?, :respond_to_missing?, :reverse_each, :select, :select!, :send, :singleton_class, :singleton_methods, :size, :slice_before, :sort, :sort_by, :subset?, :subtract, :superset?, :taint, :tainted?, :take, :take_while, :tap, :to_a, :to_enum, :to_s, :to_set, :trust, :union, :untaint, :untrust, :untrusted?, :zip, :|]




【参考】
The Book Of Ruby
Ruby 1.9.3 API
相关文章
|
5月前
|
存储 NoSQL API
【Redis 系列】redis 学习四,set 集合,hash 哈希,zset 有序集合初步认知
【Redis 系列】redis 学习四,set 集合,hash 哈希,zset 有序集合初步认知
|
1月前
|
存储 NoSQL Java
【Redis】1、学习 Redis 的五大基本数据类型【String、Hash、List、Set、SortedSet】
【Redis】1、学习 Redis 的五大基本数据类型【String、Hash、List、Set、SortedSet】
53 0
|
3月前
|
存储 消息中间件 缓存
Redis不止能存储字符串,还有List、Set、Hash、Zset,用对了能给你带来哪些优势?
Redis不止能存储字符串,还有List、Set、Hash、Zset,用对了能给你带来哪些优势?
|
8月前
|
存储 缓存 NoSQL
【Redis】集合(Hash、List、Set、ZSet)的底层实现原理
【Redis】集合(Hash、List、Set、ZSet)的底层实现原理
|
9月前
|
存储 缓存 NoSQL
【原创】详细案例解剖——浅谈Redis缓存的常用5种方式(String,Hash,List,set,SetSorted )
【原创】详细案例解剖——浅谈Redis缓存的常用5种方式(String,Hash,List,set,SetSorted )
|
存储 缓存 NoSQL
redis 五种数据结构常用操作命令详解(String,list,set,zset,hash)
🍅程序员小王的博客:程序员小王的博客 🍅 欢迎点赞 👍 收藏 ⭐留言 📝 🍅 如有编辑错误联系作者,如果有比较好的文章欢迎分享给我,我会取其精华去其糟粕 🍅java自学的学习路线:
257 0
redis 五种数据结构常用操作命令详解(String,list,set,zset,hash)
|
存储 NoSQL 安全
一步一步学习Redis——五大数据类型(String、Hash、List、Set、ZSet)简要介绍
一步一步学习Redis——五大数据类型(String、Hash、List、Set、ZSet)简要介绍
一步一步学习Redis——五大数据类型(String、Hash、List、Set、ZSet)简要介绍
|
存储 编解码 缓存
春眠不觉晓,Redis数据类型知多少?String,List,Set,SortedSet,Hash,Bitmap,HyperLogLogs
Redis不是一个简单的键值对存储,它实际上是一个支持各种类型数据结构的存储。在传统的键值存储中,是将字符串键关联到字符串值,但是在Redis中,这些值不仅限于简单的字符串,还可以支持更复杂的数据结构。下面就是Redis支持的数据结构:
133 0
春眠不觉晓,Redis数据类型知多少?String,List,Set,SortedSet,Hash,Bitmap,HyperLogLogs
|
NoSQL Redis 数据库
REDIS03_概述、安装、key、字符串String、列表List、集合Set、Hash哈希、Zset有序集合、持久化策略(九)
REDIS03_概述、安装、key、字符串String、列表List、集合Set、Hash哈希、Zset有序集合、持久化策略(九)
REDIS03_概述、安装、key、字符串String、列表List、集合Set、Hash哈希、Zset有序集合、持久化策略(九)
|
NoSQL Redis
REDIS03_概述、安装、key、字符串String、列表List、集合Set、Hash哈希、Zset有序集合、持久化策略(八)
REDIS03_概述、安装、key、字符串String、列表List、集合Set、Hash哈希、Zset有序集合、持久化策略(八)
REDIS03_概述、安装、key、字符串String、列表List、集合Set、Hash哈希、Zset有序集合、持久化策略(八)