Ruby Set类:相等的集合 [英] Ruby Set class: equality of sets

查看:84
本文介绍了Ruby Set类:相等的集合的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

根据Ruby Set类的文档, ==如果两个集合相等,则返回true。每对元素的相等性是根据Object#eql?定义的。

According to the Ruby Set class's documentation, "== Returns true if two sets are equal. The equality of each couple of elements is defined according to Object#eql?.

使用Date对象可以证明其本质,其中包含不同Date对象但具有相同日期的集合比较等于:

The essence of this can be demonstrated using Date objects, where sets containing different Date objects but with the same date compare to equal:

require 'set'
d1 = Date.today              # => Thu, 30 Sep 2010
puts d1.object_id            # => 2211539680
d2 = Date.today + 1          # => Fri, 01 Oct 2010
puts d2.object_id            # => 2211522320
set1 = Set.new([d1, d2])

d11 = Date.today             # => Thu, 30 Sep 2010
puts d11.object_id           # => 2211489080
d12 = Date.today + 1         # => Fri, 01 Oct 2010
puts d12.object_id           # => 2211469380
set2 = Set.new([d12, d11])

set1 == set2                 # => true

但是使用我自己的对象s,我在哪里编码eql?仅比较某些属性的方法,我无法使用它。

But using my own objects, where I've coded the eql? method to only compare certain attributes, I can't get it to work.

class IpDet

    attr_reader :ip, :gateway

    def initialize(ip, gateway, netmask, reverse)
        @ip = ip
        @gateway = gateway
        @netmask = netmask
        @reverse = reverse
    end

    def eql?(other)
        if @ip = other.ip && @gateway == other.gateway
            return true
        else
            return false
        end
    end
end



ipdet1 = IpDet.new(123456, 123457, 123458, 'example.com')
ipdet2 = IpDet.new(234567, 2345699, 123458, 'nil')

ipdet11 = IpDet.new(123456, 123457, 777777, 'other_domain.com')
ipdet12 = IpDet.new(234567, 2345699, 777777, 'example.com')

puts "ipdet1 is equal to ipdet11: #{ipdet1.eql?(ipdet11)}"
puts "ipdet2 is equal to ipdet12: #{ipdet2.eql?(ipdet12)}"


set1 = Set.new([ipdet1, ipdet2])
set2 = Set.new([ipdet11, ipdet12])

puts "set 1 is equal to set2: #{set1 == set2}"

我从上面得到的输出是:

The output I get from the above is:

ipdet1 is equal to ipdet11: true
ipdet2 is equal to ipdet12: true
set 1 is equal to set2: false

有任何想法吗?

推荐答案

当覆盖 eql?时,您还始终需要覆盖 hash ,使得 o1。 eql?(o2)是真实的, o1.hash == o2.hash 也是真实的。

When you override eql?, you also always need to override hash such that if o1.eql?(o2) is true, o1.hash == o2.hash is also true.

例如,您的哈希方法可能如下所示:

For example your hash method could look like this:

def hash
  [@ip, @gateway].hash
end

此外,您在 eql?方法: @ip = other.ip 应该为 @ip == other.ip

Also you have a typo in your eql? method: @ip = other.ip should be @ip == other.ip.

还有一个次要的注释:如果条件为true,则为false结束仅等于 condition ,因此您的 eql?方法可以定义为

Also a minor stylenote: if condition then true else false end is equivalent to just condition, so your eql? method can just be defined as

def eql?(other)
  @ip == other.ip && @gateway == other.gateway
end

这篇关于Ruby Set类:相等的集合的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆