Skip to content

Instantly share code, notes, and snippets.

@wycleffsean
Created June 6, 2017 21:42
Show Gist options
  • Save wycleffsean/877d49848cde9622a1a08669366bd3fc to your computer and use it in GitHub Desktop.
Save wycleffsean/877d49848cde9622a1a08669366bd3fc to your computer and use it in GitHub Desktop.
Grouping by expression
require 'securerandom'
require 'pp'
Ex = Struct.new(:a,:b,:c,:d)
module Enumerable
def group(&block)
groups = Hash.new
each do |item|
matches = []
groups.each do |key, values|
values.each do |value|
if block.call(item, value)
matches << key
break
end
end
end
case matches.length
when 0
# create group
groups[SecureRandom.uuid] = [item]
when 1
# join group
groups[matches.first] << item
else
# merge groups
key = matches.shift
matches.each do |matched_key|
groups[key].concat groups[matched_key]
groups.delete(matched_key)
end
# join merged group
groups[key] << item
end
end
groups.values
end
end
uuid = -> { SecureRandom.uuid }
one_group = [
Ex.new(1, uuid[], uuid[], uuid[]),
Ex.new(1, 2, uuid[], uuid[]),
Ex.new(uuid[], 2, 3, uuid[]),
Ex.new(uuid[], uuid[], 3, 4),
Ex.new(uuid[], uuid[], uuid[], 4),
]
two_groups = [
Ex.new(1, uuid[], uuid[], uuid[]),
Ex.new(1, 2, uuid[], uuid[]),
Ex.new(uuid[], uuid[], 3, uuid[]),
Ex.new(uuid[], uuid[], 3, 4),
Ex.new(uuid[], uuid[], uuid[], 4),
]
one_bridged_group = [
Ex.new(1, uuid[], uuid[], uuid[]),
Ex.new(uuid[], uuid[], 3, 4),
Ex.new(1, 2, uuid[], uuid[]),
Ex.new(uuid[], uuid[], uuid[], 4),
Ex.new(uuid[], 2, 3, uuid[]),
]
matcher = lambda do |x, y|
x.a == y.a ||
x.b == y.b ||
x.c == y.c ||
x.d == y.d
end
def assert(expected_length, grouped)
puts grouped.length == expected_length ? 'Worked' : 'Failed'
pp grouped
end
puts '=== One Group'
assert 1, one_group.group(&matcher)
puts '=== Two Groups'
assert 2, two_groups.group(&matcher)
puts '=== One Bridged Group'
assert 1, one_bridged_group.group(&matcher)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment