f = -> a {
w = a.map {|s| s.split('=')}.flatten.uniq.map.with_index.to_h
a.each_with_object([]) {|s, acc|
x, xa, y, ya = s.split('=').map {|k| [k, acc.find {|b| b.include? k}]}.flatten(1)
if xa && ya then xa.concat (acc.delete ya)
elsif xa then xa << y
elsif ya then ya << x
else acc << [x, y]
end
}.map {|a| a.sort_by {|s| w[s]}}.sort_by {|a| w[a[0]]}
}
a = ["a1=a2", "b1=b2", "b3=b2", "c1=c2", "e1=e2",
"a3=a4", "c3=c4", "e1=e3", "a2=a4", "c3=c1",
"b3=a4", "c2=d1", "a4=a5", "d2=c1", "b4=b3", "d3=c3"]
p f.(a)
ZiA9IC0+IGEgewogIHcgPSBhLm1hcCB7fHN8IHMuc3BsaXQoJz0nKX0uZmxhdHRlbi51bmlxLm1hcC53aXRoX2luZGV4LnRvX2gKICBhLmVhY2hfd2l0aF9vYmplY3QoW10pIHt8cywgYWNjfAogICAgeCwgeGEsIHksIHlhID0gcy5zcGxpdCgnPScpLm1hcCB7fGt8IFtrLCBhY2MuZmluZCB7fGJ8IGIuaW5jbHVkZT8ga31dfS5mbGF0dGVuKDEpCiAgICBpZiB4YSAmJiB5YSB0aGVuIHhhLmNvbmNhdCAoYWNjLmRlbGV0ZSB5YSkKICAgIGVsc2lmIHhhIHRoZW4geGEgPDwgeQogICAgZWxzaWYgeWEgdGhlbiB5YSA8PCB4CiAgICBlbHNlIGFjYyA8PCBbeCwgeV0KICAgIGVuZAogIH0ubWFwIHt8YXwgYS5zb3J0X2J5IHt8c3wgd1tzXX19LnNvcnRfYnkge3xhfCB3W2FbMF1dfQp9CmEgPSBbImExPWEyIiwgImIxPWIyIiwgImIzPWIyIiwgImMxPWMyIiwgImUxPWUyIiwKImEzPWE0IiwgImMzPWM0IiwgImUxPWUzIiwgImEyPWE0IiwgImMzPWMxIiwKImIzPWE0IiwgImMyPWQxIiwgImE0PWE1IiwgImQyPWMxIiwgImI0PWIzIiwgImQzPWMzIl0KcCBmLihhKQo=
[["a1", "a2", "b1", "b2", "b3", "a3", "a4", "a5", "b4"], ["c1", "c2", "c3", "c4", "d1", "d2", "d3"], ["e1", "e2", "e3"]]