Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

array in hash... argh!!

1 view
Skip to first unread message

Marco

unread,
Oct 21, 2005, 3:26:25 PM10/21/05
to
hello all.
i hope someone here can help me out. i really don't understand haw to do
this.
i have a hash like this:

"movies"=>{
"title"=>["ciccio", "test", "ciccio panza"],
"id"=>["3", "4", "1"],
"description"=>["1", "", "hey?"],
"insert_date"=>["2005-10-19", "2005-10-20", "2005-10-18"]
}

and i wold like to get 3 hashes like tese:

first hash:
"movie"=>{
"title"=>"ciccio",
"id"=>"3",
"description"=>"1",
"insert_date"=>"2005-10-19"
}

second hash:
"movie"=>{
"title"=>"test",
"id"=>"4",
"description"=>"",
"insert_date"=>"2005-10-19"
}

and so on.

is this somehow possible?
thanks!

Jamis Buck

unread,
Oct 21, 2005, 3:38:46 PM10/21/05
to
On Oct 21, 2005, at 1:26 PM, Marco wrote:

> hello all.
> i hope someone here can help me out. i really don't understand haw
> to do this.
> i have a hash like this:

I'm always up for a good game of golf. :)

>
> "movies"=>{
> "title"=>["ciccio", "test", "ciccio panza"],
> "id"=>["3", "4", "1"],
> "description"=>["1", "", "hey?"],
> "insert_date"=>["2005-10-19", "2005-10-20", "2005-10-18"]
> }

hashes = []
hash["movies"].keys.each do |key|
hash["movies"][key].each_with_index do |value, idx|
hashes[idx] ||= {}
hashes[idx][key] = value
end
end
p hashes

Not optimized for brevity, but it works.

- Jamis

Edward Faulkner

unread,
Oct 21, 2005, 3:46:16 PM10/21/05
to

Assuming this:

movies={


"title"=>["ciccio", "test", "ciccio panza"],
"id"=>["3", "4", "1"],
"description"=>["1", "", "hey?"],
"insert_date"=>["2005-10-19", "2005-10-20", "2005-10-18"]
}

Then this returns an array containing three hashes, one for each
movie:

movies.values[0].zip(*a.values[1..-1]).map{|x| Hash[*a.keys.zip(x).flatten]}

regards,
Ed

signature.asc

Marco

unread,
Oct 21, 2005, 4:00:18 PM10/21/05
to

hey thank you both!! Edward, i will probably never understand your
one-liner :) (trying to do that now)

And tmanks Jamis too!

Edward Faulkner

unread,
Oct 21, 2005, 4:00:03 PM10/21/05
to
On Fri, Oct 21, 2005 at 03:43:49PM -0400, Edward Faulkner wrote:
> movies.values[0].zip(*a.values[1..-1]).map{|x| Hash[*a.keys.zip(x).flatten]}

Oops, I meant this:

movies.values[0].zip(*movies.values[1..-1]).map{|x| Hash[*movies.keys.zip(x).flatten]}

(don't rename your variables when you move from irb to email ;-)

signature.asc

Simon Strandgaard

unread,
Oct 21, 2005, 4:03:37 PM10/21/05
to
On 10/21/05, Marco <z@a.b> wrote:
[snip]

> and i wold like to get 3 hashes like tese:
>


h = {


"title"=>["ciccio", "test", "ciccio panza"],
"id"=>["3", "4", "1"],
"description"=>["1", "", "hey?"],
"insert_date"=>["2005-10-19", "2005-10-20", "2005-10-18"]
}

vals = h.map{|k,v| v}.transpose
keys = h.map{|k,v| k}
ary_of_pairs = vals.map{|ary| keys.zip(ary)}
res = ary_of_pairs.map{|pairs| Hash[*pairs]}
puts res.map{|hash| hash.inspect }.join("\n")


=begin
output:

{["title", "ciccio"]=>["id", "3"], ["description",
"1"]=>["insert_date", "2005-10-19"]}
{["description", ""]=>["insert_date", "2005-10-20"], ["title",
"test"]=>["id", "4"]}
{["title", "ciccio panza"]=>["id", "1"], ["description",
"hey?"]=>["insert_date", "2005-10-18"]}

=end

--
Simon Strandgaard


Simon Strandgaard

unread,
Oct 21, 2005, 4:09:17 PM10/21/05
to
On 10/21/05, Simon Strandgaard <neo...@gmail.com> wrote:
> On 10/21/05, Marco <z@a.b> wrote:
> [snip]
> > and i wold like to get 3 hashes like tese:
> >
>
>
> h = {
> "title"=>["ciccio", "test", "ciccio panza"],
> "id"=>["3", "4", "1"],
> "description"=>["1", "", "hey?"],
> "insert_date"=>["2005-10-19", "2005-10-20", "2005-10-18"]
> }
>
> vals = h.map{|k,v| v}.transpose
> keys = h.map{|k,v| k}
> ary_of_pairs = vals.map{|ary| keys.zip(ary)}
> res = ary_of_pairs.map{|pairs| Hash[*pairs]}
> puts res.map{|hash| hash.inspect }.join("\n")

a bit shorter..

res = h.values.transpose.map{|ary| h.keys.zip(ary)}.map{|pairs| Hash[*pairs]}

Trans

unread,
Oct 21, 2005, 4:10:55 PM10/21/05
to
Could be shorter but I worry about hash order:

hm = hash['movies']
keys,values = hm.keys,hm.values
h = values.transpose
h.inject([]){ |m,e| m << {'movie' => Hash[*keys.zip(e).flatten]} }

T.

Edward Faulkner

unread,
Oct 21, 2005, 4:22:07 PM10/21/05
to
On Sat, Oct 22, 2005 at 05:09:17AM +0900, Simon Strandgaard wrote:
> a bit shorter..
>
> res = h.values.transpose.map{|ary| h.keys.zip(ary)}.map{|pairs| Hash[*pairs]}

Ah, transpose! That's what I was looking for. And as long as we're
golfing... no need for two maps:

res = h.values.transpose.map{|ary| Hash[*h.keys.zip(ary).flatten]}

regards,
Ed

signature.asc

Simon Strandgaard

unread,
Oct 21, 2005, 4:22:39 PM10/21/05
to
On 10/21/05, Simon Strandgaard <neo...@gmail.com> wrote:
> On 10/21/05, Simon Strandgaard <neo...@gmail.com> wrote:
> > On 10/21/05, Marco <z@a.b> wrote:
> > [snip]
> > > and i wold like to get 3 hashes like tese:
> > >
> >
> >
> > h = {
> > "title"=>["ciccio", "test", "ciccio panza"],
> > "id"=>["3", "4", "1"],
> > "description"=>["1", "", "hey?"],
> > "insert_date"=>["2005-10-19", "2005-10-20", "2005-10-18"]
> > }
> >
> > vals = h.map{|k,v| v}.transpose
> > keys = h.map{|k,v| k}
> > ary_of_pairs = vals.map{|ary| keys.zip(ary)}
> > res = ary_of_pairs.map{|pairs| Hash[*pairs]}
> > puts res.map{|hash| hash.inspect }.join("\n")
>
> a bit shorter..
>
> res = h.values.transpose.map{|ary| h.keys.zip(ary)}.map{|pairs| Hash[*pairs]}
>

even shorter.. I am having dinner in front of my mac..

res = h.values.transpose.map{|a|Hash[*h.keys.zip(a)]}
p res

--
Simon Strandgaard


Trans

unread,
Oct 21, 2005, 4:27:43 PM10/21/05
to
> res = h.values.transpose.map{|a|Hash[*h.keys.zip(a)]}

Dang that's short!

But I wonder, is it any possiblity that h.keys won't be the same order
as h.values?

T.

Simon Strandgaard

unread,
Oct 21, 2005, 4:37:07 PM10/21/05
to
On 10/21/05, Trans <tran...@gmail.com> wrote:
> > res = h.values.transpose.map{|a|Hash[*h.keys.zip(a)]}
>
> Dang that's short!

hehe


> But I wonder, is it any possiblity that h.keys won't be the same order
> as h.values?

I think it the same as:

vals = h.map{|k,v| v}

keys = h.map{|k,v| k}

so hopefully order is the same..

--
Simon Strandgaard


Mark J. Reed

unread,
Oct 21, 2005, 5:07:35 PM10/21/05
to
Simon Strandgaard <neo...@gmail.com> writes:
>even shorter.. I am having dinner in front of my mac..

>res =3D h.values.transpose.map{|a|Hash[*h.keys.zip(a)]}

That doesn't quite work. You need to flatten the result of each zip, as posted earlier:

movies.values.transpose.map{|a|Hash[*movies.keys.zip(a).flatten]}

Your version yields this on the given input, which is not quite right:

[{["title", "ciccio"]=>["id", "3"], ["description", "1"]=>["insert_date", "2005-10-19"]},
{["description", ""]=>["insert_date", "2005-10-20"], ["title", "test"]=>["id", "4"]},
{["title", "ciccio panza"]=>["id", "1"], ["description", "hey?"]=>["insert_date", "2005-10-18"]}]

In fact, it would raise an exception if there didn't happen to be an even number of fields per
record.

Simon Strandgaard

unread,
Oct 21, 2005, 5:20:54 PM10/21/05
to
On 10/21/05, Mark J. Reed <mr...@thereeds.org> wrote:
> Simon Strandgaard <neo...@gmail.com> writes:
> >even shorter.. I am having dinner in front of my mac..
>
> >res =3D h.values.transpose.map{|a|Hash[*h.keys.zip(a)]}
>
> That doesn't quite work. You need to flatten the result of each zip, as posted earlier:
>
> movies.values.transpose.map{|a|Hash[*movies.keys.zip(a).flatten]}

my bad.. sorry.

--
Simon Strandgaard


Dave Burt

unread,
Oct 22, 2005, 2:30:48 AM10/22/05
to
Trans:
> keys,values = hm.keys,hm.values

Doesn't that have the same potential problem, separate calls to keys and
values?

Cheers,
Dave


Mark Hubbart

unread,
Oct 22, 2005, 8:40:49 PM10/22/05
to
On 10/21/05, Jamis Buck <ja...@37signals.com> wrote:
> On Oct 21, 2005, at 1:26 PM, Marco wrote:
>
> > hello all.
> > i hope someone here can help me out. i really don't understand haw
> > to do this.
> > i have a hash like this:
>
> I'm always up for a good game of golf. :)

what? did I hear "golf"? :D

> > "movies"=>{
> > "title"=>["ciccio", "test", "ciccio panza"],
> > "id"=>["3", "4", "1"],
> > "description"=>["1", "", "hey?"],
> > "insert_date"=>["2005-10-19", "2005-10-20", "2005-10-18"]
> > }

Not as short as some, but we gotta throw a short inject version in somewhere:

h.inject([]){|a,(k,s)|i=-1;s.map{|v|a[i+=1]||={};a[i][k]=v};a}

cheers,
Mark


Mark Hubbart

unread,
Oct 22, 2005, 8:45:55 PM10/22/05
to

shaved off a few more chars:

h.inject([]){|a,(k,s)|i=-1;s.map{|v|(a[i+=1]||={})[k]=v};a}

Okay, that's it. I just realized this thread is a little old :)

cheers,
Mark


0 new messages