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) << x << y
elsif xa then xa << x << y
elsif ya then ya << x << y
else acc << [x, y]
end
}.map {|a| a.uniq.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+IGEgewogIHcgPSBhLm1hcCB7fHN8IHMuc3BsaXQoJz0nKX0uZmxhdHRlbi51bmlxLm1hcC53aXRoX2luZGV4LnRvX2gKICBhLmVhY2hfd2l0aF9vYmplY3QoW10pIHt8cywgYWNjfAogICAgeCwgeGEsIHksIHlhID0gcy5zcGxpdCgnPScpLm1hcCB7fGt8IFtrLCBhY2MuZmluZCB7fGJ8IGIuaW5jbHVkZT8ga31dfS5mbGF0dGVuKDEpCiAgICBpZiB4YSAmJiB5YSB0aGVuIHhhLmNvbmNhdCAoYWNjLmRlbGV0ZSB5YSkgPDwgeCA8PCB5CiAgICBlbHNpZiB4YSB0aGVuIHhhIDw8IHggPDwgeQogICAgZWxzaWYgeWEgdGhlbiB5YSA8PCB4IDw8IHkKICAgIGVsc2UgYWNjIDw8IFt4LCB5XQogICAgZW5kCiAgfS5tYXAge3xhfCBhLnVuaXEuc29ydF9ieSB7fHN8IHdbc119fS5zb3J0X2J5IHt8YXwgd1thWzBdXX0KfQphID0gWyJhMT1hMiIsICJiMT1iMiIsICJiMz1iMiIsICJjMT1jMiIsICJlMT1lMiIsCiJhMz1hNCIsICJjMz1jNCIsICJlMT1lMyIsICJhMj1hNCIsICJjMz1jMSIsCiJiMz1hNCIsICJjMj1kMSIsICJhND1hNSIsICJkMj1jMSIsICJiND1iMyIsICJkMz1jMyJdCnAgZi4oYSkK
[["a1", "a2", "b1", "b2", "b3", "a3", "a4", "a5", "b4"], ["c1", "c2", "c3", "c4", "d1", "d2", "d3"], ["e1", "e2", "e3"]]