zoukankan      html  css  js  c++  java
  • ruby中Hash的自定义key

    Hash主要使用Key中的两个函数:hash和eql? hash返回的是对象的hash值,eql?是用来对比两个对象是不是相等。

    回顾下Hash这种数据结构,其首先需要一个hash函数返回一个整数,ruby中为Fixnum,然后根据Fixnum去使用eql?判断两个object是不是相同。

    所以,如果只是改变了hash函数,就仅仅会让具有相同实例的objecthash到同一个Fixnum,但是eql?不相等,也没有办法当成同一个key。同样,如果只修改eql?,相同字段的object可能都没有办法hash到同一个Fixnum,那么同样也没有办法当作同一个key。


    为了说明这两个函数的用处,我将分四种情况讨论。

    情况1)定义一个Kiwi,不改变hash和eql?

    class Kiwi
    	attr_reader :id, :name
    
    	def initialize(id, name)
    		@id = id
    		@name = name
    	end
    end
    Kiwi.new(1, "kiwi").eql?(Kiwi.new(1, "kiwi"))  #=> false
    hash = Hash.new #=> {}
    hash[Kiwi.new(1, "kiwi")]  = 1  #=> {#<Kiwi:0x00000001ec8230 @id=1, @name="kiwi">=>1}
    hash[Kiwi.new(1, "kiwi")]     #=> nil


    从情况1中,我们可以看出在没有重写hash和eql?的情况下,虽然Kiwi的两个实例字段相同,但是不能相等,同时,hash具有相同字段的Kiwi实例,也不能得到结果。


    情况2)仅修改hash,不修改eql?

    class Kiwi
    	attr_reader :id, :name
    
    	def initialize(id, name)
    		@id = id
    		@name = name
    	end
    	def hash
    		@id.hash
    	end
    end
    Kiwi.new(1, "kiwi").eql?(Kiwi.new(1, "kiwi"))  #=> false
    hash = Hash.new #=> {}
    hash[Kiwi.new(1, "kiwi")]  = 1  #=> {#<Kiwi:0x00000000c38de0 @id=1, @name="kiwi">=>1}
    hash[Kiwi.new(1, "kiwi")]     #=> nil

    结果与情况1中相同


    情况3)仅修改eql?

    class Kiwi
    	attr_reader :id, :name
    
    	def initialize(id, name)
    		@id = id
    		@name = name
    	end
    	def eql?(other)
    		self.class.equal?(other.class) && @id == other.id && @name == other.name
    	end
    end
    Kiwi.new(1, "kiwi").eql?(Kiwi.new(1, "kiwi"))  #=> true
    hash = Hash.new #=> {}
    hash[Kiwi.new(1, "kiwi")]  = 1  #=>{#<Kiwi:0x00000000f5ba90 @id=1, @name="kiwi">=>1}
    hash[Kiwi.new(1, "kiwi")]     #=> nil

    可以看出当Kiwi两个实例变量相同的相同的时候,Kiwi即相等


    情况4)同时修改hash和eql?

    class Kiwi
    	attr_reader :id, :name
    
    	def initialize(id, name)
    		@id = id
    		@name = name
    	end
    	def eql?(other)
    		self.class.equal?(other.class) && @id == other.id && @name == other.name
    	end
    	def hash
    		@id.hash
    	end
    end
    Kiwi.new(1, "kiwi").eql?(Kiwi.new(1, "kiwi"))  #=> true
    hash = Hash.new #=> {}
    hash[Kiwi.new(1, "kiwi")]  = 1  #=>  {#<Kiwi:0x00000000b928f0 @id=1, @name="kiwi">=>1}
    hash[Kiwi.new(1, "kiwi")]     #=> 1

    这下就只要kiwi的实例变量相同,都被当成同一个key了


  • 相关阅读:
    ASP.NET 使用Ajax(转)
    使用Docker,很多坑(之一):在windows中使用
    .NET Core 各种学习资源
    docker-compose.yml配置文件详解(转)
    英雄无敌王国刷将脚本
    Valid format values for declare-styleable/attr tags[转]
    no Session问题,即延迟加载
    适配器模式--Adapter Pattern
    策略模式--Strategy
    装饰模式--Decorator Pattern
  • 原文地址:https://www.cnblogs.com/java20130722/p/3206853.html
Copyright © 2011-2022 走看看