Ruby中的Hash哈希类型基本操作方法小结

1.创建哈希:就像创建数组一样,我们可以通过Hash类来创建一个Hash实例:

h1 = Hash.new             #默认值为nil
h2 = Hash.new(“This is my first hash instance”) #默认值为” This is my first hash instance”:

上面两个例子都创建了一个空的Hash实例。一个Hash对象总是有一个默认的值——因为如果在一个Hash对象里没有找到指定的索引(key),将会返回默认值。
创建了Hash对象后,我们就可以像数组那样给他添加/删除项了。唯一不同的是,在数组中的索引只是能整数,而在Hash中索引(key)可以是任何类型(any type of object)且唯一的数据:

h2["one"] = "北京"
h2["two"] = "上海"
h2["three"] = "深圳"
h2["four"] = "广州"

Note: 如果在给Hash赋值时,使用的相同的key,那么后面的值会覆盖掉前面的值。另外,Ruby还提供了一种方便的创建和初始化Hash的方法,只需要在key后面加一个=>符号并跟一个值即可。每个key-value对用逗号隔开。然后整体用大括号括起来:

h2 = {
"one" => "北京",
"two" =>"上海",
"three" =>"深圳",
"four" =>"广州"
}

2.通过索引存取Hash的值:
要想获取某个值,可以用下面的方法:

  puts h2[“one”]    #=>”北京”

如果指定的key不存在,将返回默认的值(前面有提到过)。此外,我们还可以用default方法获取默认值,用default+=方法设置默认值

    puts h1.default
    h1.default += “This is set value method”

 
3.复制Hash:
和数组一样,我们可以把一个Hash变量分配给另一个hash变量,它们都引用想同的Hash,所以如果其中一个的值变了,那么另外一个的值也会跟着变:

  h3 = h2
  h3[“one”] = “西安”
  puts h h2[“one”]    #=>”西安”

有的时候我们不希望上面的情况发生,即:修改了其中一个的值另一个也跟着修改了,我们可以使用clone方法make a new copy

  h4 = h2.clone
  h4[“one”] = “大连”
  puts h2[“one”]       #=>”西安”(i.e. 值没有修改)

4.Hash排序:
当我们需要对Hash进行排序时,不能像数组那样简单的使用sort方法,因为数组中的数据类型都是一样的(整型),Hash中的数据类型可能并不完全一样,如整数类型和字符串类型就没法一起排序,此时就需要我们进行处理,如下(如果Hash中的数据类型全部相同可以不进行如下处理):

  def sorted_hash(aHash)
    return aHash.sort{
      |a,b| a.to_s <=> b.to_s
    }
  End
h1 = {1=>'one', 2=>'two', 3=> 'three'}
h2 = {6=>'six', 5=>'five', 4=> 'four'}
h3 = {'one'=>'A', 'two'=>'B','three'=>'C'}
h4 = h1.merge(h2)      #合并hash
h5 = h1.merge(h3)
def sorted_hash(aHash)
 return aHash.sort{|a,b| a.to_s <=> b.to_s }
end
p(h4)
p(h4.sort)
p(h5)
p(sorted_hash(h5))

结果

{5=>"five", 6=>"six", 1=>"one", 2=>"two", 3=>"three", 4=>"four"}
[[1, "one"], [2, "two"], [3, "three"], [4, "four"], [5, "five"], [6, "six"]]
{"two"=>"B", "three"=>"C", 1=>"one", 2=>"two", "one"=>"A", 3=>"three"}
[[1, "one"], [2, "two"], [3, "three"], ["one", "A"], ["three", "C"], ["two", "B"]]

事实上Hash的sort方法是把一个Hash对象转换成以[key,value]为单个元素的一个数组,然后再用数组的sort方法进行排序。

5.Hash类常用方法:


方法


说明


size()


返回Hash对象的长度


length()


返回Hash对象的长度


include?(key)


判断指定的Hash对象是否包含指定的key


has_key?(key)


判断指定的Hash对象是否包含指定的key


delete(key)


删除Hash对象中指定key的对应元素


keys()


返回由Hash对象中全部key组成的数组


values()


返回由Hash对象中全部value组成的数组

e.g.

  student = {
     "name" => "Steve",
     "age" => 22,
     "Gender" => "male"
    }
  p student.keys              #=> ["name", "Gender", "age"]
  p student.values             #=> ["Steve", "male", 22]
  puts student.include?("age")         #=> true
  puts student.size             #=> 3
  student.delete("Gender")
  puts student.has_key?("Gender")       #=>false
  puts student.size             #=>2

6.Hash的转换使用
在处理嵌套了几层的hash时,总是感觉很混乱,读取、修改时都很麻烦。因此想到把hash转换为对象,直接生成key的get/set方法,代码如下:

class HashObj
 class << self
 def load_from_hash(hash)
  if hash.instance_of? Hash
  obj = HashObj.new
  hash.each{|k,v| obj.send :def_sget_method,k,HashObj.load_from_hash(v)}
  obj
  elsif hash.instance_of? Array
  hash.map{|m| HashObj.load_from_hash(m) }
  else
  hash
  end
 end
 end

 def attributes
 hash = {}
 @@reg ||= /=/
 self.singleton_methods.reject{|x| @@reg =~ x.to_s}.each do |m|
  v = self.send(m)
  if v.instance_of? HashObj
  real_v = v.attributes
  elsif v.instance_of? Array
  real_v = []
  v.each do |l|
   if l.instance_of? HashObj
   real_v << l.attributes
   else
   real_v << l
   end
  end
  else
  real_v = v
  end
  hash[m] = real_v
 end
 hash
 end

 protected
 def def_sget_method(name,val)
 self.instance_variable_set "@#{name}",val

 self.define_singleton_method "#{name}=" do |n_val|
  instance_variable_set "@#{name}",n_val
 end

 self.define_singleton_method name do
  instance_variable_get "@#{name}"
 end
 end
end

使用demo

hash = {name:'jack',age:22,phone:['61900871','8787876'],
    basic_info:{country:'USA',city:'New York'}}
obj = HashObj.load_from_hash hash
obj.name #'jack'
obj.age  #22
obj.phone #['61900871','8787876']
obj.basic_info #<HashObj:0x007f9eda02b360 @country="USA", @city="New York">
obj.basic_info.country #'USA'
obj.attributes == hash #true
obj.age = 30
obj.attributes #{:name=>"jack", :age=>30, :phone=>["61900871", "8787876"],
# :basic_info=>{:country=>"USA", :city=>"New York"}}
(0)

相关推荐

  • Ruby字符串、条件、循环、数组、Hash、类基本操作笔记

    一.字符串操作 字符串插值 1.#{}: 任意放置在#{}中的合法Ruby代码都将被求值,并被替换为求值结果插入到原位置 2.单引号与双引号差别: 双引号允许字符转义,单引号不允许转义,里是什么字符,用户看到的就是什么字符 单引号不允许字符插值 字符串拆分 1.以空格拆分:string.split(' ')字符串连接 方法一.'Ruby' + 'Monk', stdout: RubyMonk 方法二."Monk".concat("Ruby") stdout: Mon

  • Ruby中关于hash的基本使用方法

    哈希键 - 值对的集合,类似这样:"employee" => "salary".它类似于数组,除了索引是通过任意键的任何对象的类型,而不是一个整数索引. 顺序遍历一个哈希键或值要么可能看起来是任意的,一般不会在插入顺序.如果访问的键的哈希值不存在,该方法将返回nil. 创建哈希: 使用数组中,有各种各样的方法来创建哈希值.可以 new 类方法创建一个空的hash : months = Hash.new 还可以使用 new 创建哈希,这是一个默认值,否则只是 n

  • Ruby简明教程之数组和Hash介绍

    今天学习的是数组和Hash,数组在很多编程语言中都能常常用到. 数组: 数组是存储数据的一种容器,在Ruby中,数组中存储的数据可以是任何类型的数据:这和JAVA不同,在JAVA中,数组是存储同一类型数据的结构. 1. 在Ruby中如何定义数组呢? 使用[ ]来框住元素,而元素之间则使用","间隔.如下, 复制代码 代码如下: name = ["Windy", "Cindy", "Amee", "Tom"]

  • Ruby中Hash的11个问题解答

    最近在学习Rails,因为学习的java为入门语言.些许的不太适应.特别是Ruby的Hash.不过细细的想想就通了.基本上都是通的Key-Value.除了刚开始不太适应写法没什么大的问题.这个是我在网上看到的一篇日志. 1. 如何创建Hash? 复制代码 代码如下: x = Hash.new x = {} x = {:a => 1, :b => 2} 这些都是创建Hash的方法. 第一个和第二个一样,表示创建空的Hash. 第三个表示创建的Hash,有2对键/值. 2. Hash的键是哪些类型

  • Ruby中Hash哈希结构的基本操作方法小结

    关于哈希 先来了解一下Hash的基本思路: 设要存储对象的个数为num, 那么我们就用len个内存单元来存储它们(len>=num); 以每个对象ki的关键字为自变量,用一个函数h(ki)来映射出ki的内存地址,也就是ki的下标,将ki对象的元素内容全部存入这个地址中就行了.这个就是Hash的基本思路. 为什么要用一个函数来映射出它们的地址单元呢? 假设现在我要存储4个元素 13 7 14 11 显然,我们可以用数组来存.也就是:a[1] = 13; a[2] = 7; a[3] = 14; a

  • Ruby中的Hash哈希类型基本操作方法小结

    1.创建哈希:就像创建数组一样,我们可以通过Hash类来创建一个Hash实例: h1 = Hash.new #默认值为nil h2 = Hash.new("This is my first hash instance") #默认值为" This is my first hash instance": 上面两个例子都创建了一个空的Hash实例.一个Hash对象总是有一个默认的值--因为如果在一个Hash对象里没有找到指定的索引(key),将会返回默认值. 创建了Has

  • 介绍Ruby中的模块与混合类型的相关知识

    模块是组合在一起的方法,类和常量.模块两个主要好处: 模块提供了一个命名空间,并避免名称冲突. 模块实现混合工厂. 模块定义了一个命名空间,一个沙箱中方法和常量可以自由使用,而不必担心踩到其他的方法和常数. 语法: module Identifier statement1 statement2 ........... end 就像被命名为类常量模块中的常量,首字母大写.定义的方法看起来很相似,模块定义方法就像类的方法. 调用一个模块方法和类方法一样,通过模块的名称它名字前,引用一个常数使用该模块

  • Ruby中的public、private、protected区别小结

    重点关注private与protected public 默认即为public,全局都可以访问,这个不解释 private C++, "private" 意为 "private to this class", 但是Ruby中意为 "private to this instance". 意思是:C++中,对于类A,只要能访问类A,就能访问A的对象的private方法. Ruby中,却不行:你只能在你本对象的实例中访问本对象的private方法. 因

  • php操作redis中的hash和zset类型数据的方法和代码例子

    前面一篇博客主要是string类型,list类型和set类型,下面hash类型和zset类型 1,hset 描述:将哈希表key中的域field的值设为value.如果key不存在,一个新的哈希表被创建并进行HSET操作.如果域field已经存在于哈希表中,旧值将被覆盖. 参数:key field value 返回值:如果field是哈希表中的一个新建域,并且值设置成功,返回1.如果哈希表中域field已经存在且旧值已被新值覆盖,返回0. 2,hsetnx 描述:将哈希表key中的域field的

  • 详细解析Ruby中的变量

    变量持有要使用的程序的数据的存储位置. Ruby支持的有五种类型的变量.在前面的章节中已经经历了一个简短描述以及这些变量.本章中介绍的这五种类型的变量. Ruby的全局变量: 全局变量以$开头.未初始化的全局变量的值是零,并使用-w选项产生警告. 全局变量的赋值会改变全局状态.这是不推荐使用全局变量.他们使得程序的含义模糊. 下面是一个例子显示使用全局变量. #!/usr/bin/ruby $global_variable = 10 class Class1 def print_global p

  • Ruby中的迭代器详解

    D瓜哥最近想做一个网站,另外,老早就有学习一门动态语言的想法,满足着两个条件的编程语言中,Ruby.Python是最合适的两种语言.现在Ruby on Rails如日中天,光芒万丈!所以,就选定了Ruby,从零开始学习. 前天看了Ruby的迭代器,对于我这个只学过Java.C/C++等的人来说,绝对是眼前一亮的感觉!而且是光彩夺目:没想到迭代器还可以这么玩,太简练太方便而且特别强大!然后,D瓜哥就迫不及待的想写一篇文章给大家介绍介绍Ruby的迭代器! 迭代器简介 先简单介绍一下迭代器. 1.一个

  • Ruby中一些基本语法知识点的罗列汇总

    让我们写一个简单的ruby程序.所有Ruby源文件将以扩展名.rb.因此,把下面的源代码在一个test.rb文件. #!/usr/bin/ruby -w puts "Hello, Ruby!"; 在这里,假定您已经安装有Ruby解释器,可以在/usr/bin目录找到.现在尝试运行此程序如下: $ ruby test.rb 这将产生以下结果: Hello, Ruby! 通过以上实例,我们已经看到了一个简单的Ruby程序,现在让我们来看看有关Ruby语法的几个基本概念: Ruby程序中的空

  • Ruby中的数组和散列表的使用详解

    Ruby的数组(arrays)和散列表(hashes)是被索引的收集(indexed collections). 两者都存储对象的集合,通过键(key)来访问.数组的键是整数.而散列表支持以任何对象作为它的键.数组和散列表会按需调整大小来保存新的元素.访问数组元素是高效的,但是散列表提供了灵活性.任何具体的数组或散列表可以保存不同类型的对象. 使用数组字面量(array literal)--即方括号之间放一组元素--可以创建和初始化新的数组对象.有了数组对象,在方括号之间提供索引便可以访问单个元

随机推荐