From: MenTaLguY Date: 2006-06-05T03:13:39+09:00 Subject: [QUIZ][SOLUTION] Hash to OpenStruct (#81) --=-fNcGNjYRALciT9AJugFG Content-Type: text/plain Content-Transfer-Encoding: quoted-printable I've got three. ATTEMPT #1 My first attempt was pretty simple: require 'ostruct' =20 def hashes_to_openstructs( obj ) return obj unless Hash =3D=3D=3D obj OpenStruct.new( Hash[ *obj.inject( [] ) { |a, (k, v)| a.push k, hashes_to_openstructs= ( v ) } ] ) end =20 The main idea here was to build the OpenStruct all at once, rather than resorting to a bunch of Object#send( "#{name}=3D", value ) calls. To do this, however, we end up going from a hash, to a sequence of pairs, to a flat array of alternating keys and values, back to a hash, and then finally to an OpenStruct. ATTEMPT #2: Then I got bored and decided I'd deal with the case of a self-recursive hash. My first attempt used lazy.rb ( http://moonbase.rydia.net/software/lazy.rb ); I simply made the above hashes_to_openstructs() function lazy (by wrapping its innards in promise {}), then memoized it using a hash: require 'ostruct' require 'lazy' =20 def hashes_to_openstructs( obj, memo=3D{} ) return obj unless Hash =3D=3D=3D obj memo[obj.object_id] ||=3D promise { OpenStruct.new( Hash[ *obj.inject( [] ) { |a, (k, v)| a.push k, hashes_to_openstructs( v, memo ) } ] ) } end ATTEMPT #3: While that's sort of clever, I couldn't help but think there was a simpler solution. It involved building the OpenStruct incrementally, using the same Object#send calls I'd been hoping to avoid. def hashes_to_openstructs( obj, memo=3D{} ) return obj unless Hash =3D=3D=3D obj os =3D memo[obj] =3D OpenStruct.new obj.each do |k, v| os.send( "#{k}=3D", memo[v] || hashes_to_openstructs( v, memo )= ) end os end =20 Once again, however, memoization wins. -mental --=-fNcGNjYRALciT9AJugFG Content-Type: application/pgp-signature; name=signature.asc Content-Description: This is a digitally signed message part -----BEGIN PGP SIGNATURE----- Version: GnuPG v1.4.2.2 (GNU/Linux) iD8DBQBEgyKzSuZBmZzm14ERAsH5AKC0LGvFBz7lZYNq6j7gxFzjcUka1wCguHUl aa5GGbiurDeN43S9jbz6k4E= =LcXa -----END PGP SIGNATURE----- --=-fNcGNjYRALciT9AJugFG--