Array in hash... argh!

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!

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. :slight_smile:

"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

···

On Oct 21, 2005, at 1:26 PM, Marco wrote:

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!

[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

···

On 10/21/05, Marco <z@a.b> wrote:

--
Simon Strandgaard

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.

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

[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]}

···

On 10/21/05, Simon Strandgaard <neoneye@gmail.com> wrote:

On 10/21/05, Marco <z@a.b> wrote:

=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

Trans:

keys,values = hm.keys,hm.values

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

Cheers,
Dave

> 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. :slight_smile:

what? did I hear "golf"? :smiley:

> "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

···

On 10/21/05, Jamis Buck <jamis@37signals.com> wrote:

On Oct 21, 2005, at 1:26 PM, Marco wrote:

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 :wink:

···

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]}

Edward Faulkner wrote:

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]}

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

And tmanks Jamis too!

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

···

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]}

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

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

···

On 10/21/05, Simon Strandgaard <neoneye@gmail.com> wrote:

On 10/21/05, Simon Strandgaard <neoneye@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]}

--
Simon Strandgaard

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 :slight_smile:

cheers,
Mark

···

On 10/22/05, Mark Hubbart <discordantus@gmail.com> wrote:

On 10/21/05, Jamis Buck <jamis@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. :slight_smile:

what? did I hear "golf"? :smiley:

> > "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}

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 <neoneye@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.

> 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..

···

On 10/21/05, Trans <transfire@gmail.com> wrote:

--
Simon Strandgaard

my bad.. sorry.

···

On 10/21/05, Mark J. Reed <mreed@thereeds.org> wrote:

Simon Strandgaard <neoneye@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]}

--
Simon Strandgaard