ruby 44 lines · 7 steps

Diffing two hashes in Ruby

A small class that reports which keys were added, removed, or changed between two hashes.

Explained by highlit
1class HashDiff
2 Change = Struct.new(:from, :to)
3 
4 def self.call(before, after)
5 new(before, after).call
6 end
7 
8 def initialize(before, after)
9 @before = before || {}
10 @after = after || {}
11 end
12 
13 def call
14 {
15 added: added,
16 removed: removed,
17 changed: changed
18 }
19 end
20 
21 private
22 
23 attr_reader :before, :after
24 
25 def added
26 (after.keys - before.keys).each_with_object({}) do |key, memo|
27 memo[key] = after[key]
28 end
29 end
30 
31 def removed
32 (before.keys - after.keys).each_with_object({}) do |key, memo|
33 memo[key] = before[key]
34 end
35 end
36 
37 def changed
38 (before.keys & after.keys).each_with_object({}) do |key, memo|
39 next if before[key] == after[key]
40 
41 memo[key] = Change.new(before[key], after[key])
42 end
43 end
44end
01 / 01
STEP 01

Walkthrough

Space play step click any line
Three takeaways
  1. 1Array subtraction and intersection on hash keys cleanly express added, removed, and shared keys.
  2. 2each_with_object builds a result hash in one pass without a separate accumulator variable.
  3. 3A tiny Struct gives changed values a readable from/to shape instead of an opaque pair.

Related explainers

Share this explainer

Here's the card — post it anywhere.

Diffing two hashes in Ruby — share card
Made with highlit — turn any snippet into a walkthrough like this in about a minute.
Explain your code