동등성과 해시
Coddy Ruby 여정의 객체 지향 프로그래밍 섹션에 포함된 레슨. 57개 중 37번째.
Ruby에는 여러 종류의 동등성이 있습니다. ==는 값 동등성으로, 클래스에서 직접 정의합니다. 해시와 uniq는 대신 두 가지 다른 메서드인 eql?과 hash를 사용합니다. ==만 정의하면 같은 점도 여전히 서로 다른 해시 키입니다.
class Point
attr_reader :x, :y
def initialize(x, y)
@x = x
@y = y
end
def ==(other)
other.is_a?(Point) && x == other.x && y == other.y
end
end
a = Point.new(1, 2)
b = Point.new(1, 2)
puts a == b
puts [a, b].uniq.size
puts({ a => "first" }[b].inspect)출력:
true
2
nilHash는 먼저 객체에서 계산한 숫자인 hash 값을 비교한 다음, 후보를 eql?로 확인합니다. ==와 동일한 필드를 기준으로 두 메서드를 모두 정의하세요. alias eql? ==는 ==를 재사용하고, [x, y].hash는 필드들을 결합합니다:
class Point
attr_reader :x, :y
def initialize(x, y)
@x = x
@y = y
end
def ==(other)
other.is_a?(Point) && x == other.x && y == other.y
end
alias eql? ==
def hash
[x, y].hash
end
end
a = Point.new(1, 2)
b = Point.new(1, 2)
puts [a, b, Point.new(3, 4)].uniq.size
puts({ a => "first" }[b])출력:
2
first규칙은 다음과 같습니다. eql?인 객체는 같은 hash를 가져야 합니다. 서로 다른 두 객체가 우연히 같은 해시 값을 가질 수 있으므로 eql?은 여전히 확인 작업을 수행합니다. 그러면 Hash를 사용한 개수 세기는 객체의 동일성 대신 값을 기준으로 작동합니다.
class Word
attr_reader :text
def initialize(text)
@text = text.downcase
end
def ==(other)
other.is_a?(Word) && text == other.text
end
alias eql? ==
def hash
text.hash
end
end
counts = Hash.new(0)
%w[Ruby ruby RUBY gem].each { |t| counts[Word.new(t)] += 1 }
counts.each { |word, n| puts "#{word.text}: #{n}" }출력:
ruby: 3
gem: 1equal?은 객체 동일성을 유지해야 하며 절대로 재정의해서는 안 됩니다. 내장 값은 이미 이러한 규칙을 따르므로 문자열과 배열을 해시 키로 사용할 수 있습니다:
a == b # 같은 값(직접 정의함)
a.eql?(b) # Hash 키와 uniq에서 같은 값(==의 별칭)
a.hash # 숫자; 같은 객체는 같은 숫자를 반환함
a.equal?(b) # 동일한 객체(절대 재정의하지 말 것)챌린지
쉬움클래스 Point를 완성하여 좌표가 같은 점은 ==, eql? 및 hash에서 같고 Hash 키로 작동하도록 하세요. to_s는 (1, 2)를 반환합니다.
제공된 코드는 x,y 형식의 줄에서 점을 읽습니다. uniq를 사용해 서로 다른 점의 개수를 출력한 다음, Hash에서 점별 방문 횟수를 세어 첫 방문 순서대로 (1, 2): 2로 출력하고, 마지막으로 새로운 Point.new(0, 0)이 키인지 출력합니다.
코드는 point.rb에 작성하세요. main.rb에는 제공된 입출력 코드가 있으며 수정할 수 없습니다.
직접 해보기
require_relative 'point'
# 제공된 입력/출력 코드: 그대로 유지하세요
input = []
while (line = gets)
input << line.chomp
end
points = input.map { |line| Point.new(*line.split(",").map(&:to_i)) }
puts "distinct: #{points.uniq.size}"
visits = Hash.new(0)
points.each { |pt| visits[pt] += 1 }
visits.each { |pt, n| puts "#{pt}: #{n}" }
puts "origin visited: #{visits.key?(Point.new(0, 0))}"
이 레슨에는 짧은 퀴즈가 포함되어 있습니다. 레슨을 시작해 문제를 풀고 진행 상황을 기록하세요.
객체 지향 프로그래밍의 모든 레슨
직접 연습해 보세요: 온라인 Ruby 컴파일러