Array to Hash

Hi Ruby friends:

conversion fr hash to array is fine.

h
=> {“x”=>1, “y”=>3}
a = h.to_a
=> [[“x”, 1], [“y”, 3]]

no brainer there for a nuby like me :slight_smile:

but…

conversion fr array to hash… is quite a journey…

h2 = a.to_h
NoMethodError: undefined method `to_h’ for [[“x”, 1], [“y”, 3]]:Array

h2 = a.to_hash
NoMethodError: undefined method `to_hash’ for [[“x”, 1], [“y”, 3]]:Array

Finally, I got it (dug the archives)…

h2 = Hash[*a]
=> {[“x”, 1]=>[“y”, 3]}

But, it looks weird. No, not just the cryptic Hash*a, but the result as
well. I do not see any use of the result.

I would rather prefer:

h2 = a.to_hash # or a.to_h
{“x”=>1, “y”=>3}

Seems no brainer if that’s the case.
Is there any reason why not?

kind regards -botp

Peña, Botp wrote:

Finally, I got it (dug the archives)…

h2 = Hash[*a]

=> {[“x”, 1]=>[“y”, 3]}

But, it looks weird. No, not just the cryptic Hash*a, but the result as
well. I do not see any use of the result.

I would rather prefer:

h2 = a.to_hash # or a.to_h

{“x”=>1, “y”=>3}

Seems no brainer if that’s the case.
Is there any reason why not?

Well, legacy code expects a flat array of pairs… so Hash(*(a.flatten))
should work for you. But changing the way that works could break others’
code.

Yet it does seem odd that Hash.to_a doesn’t return a form that Hash[*a]
can use as-is.

Hal

Hi,

“Peña, Botp” botp@delmonte-phil.com writes:

Finally, I got it (dug the archives)…

h2 = Hash[*a]
=> {[“x”, 1]=>[“y”, 3]}

But, it looks weird. No, not just the cryptic Hash*a, but the result as
well. I do not see any use of the result.

I would rather prefer:

h2 = a.to_hash # or a.to_h
{“x”=>1, “y”=>3}

Array#flatten

h2 = Hash[*a.flatten]
=> {“x”=>1, “y”=>3}

···


eban

Hi,

At Sat, 24 Apr 2004 13:05:20 +0900,
Peña, Botp wrote in [ruby-talk:98203]:

I would rather prefer:

h2 = a.to_hash # or a.to_h
{“x”=>1, “y”=>3}

module Enumerable
def to_h
inject({}) {|h, (k, v)| h[k] = v; h}
end
end

···


Nobu Nakada

Hi –

“Peña, Botp” botp@delmonte-phil.com writes:

conversion fr hash to array is fine.

h
=> {“x”=>1, “y”=>3}
a = h.to_a
=> [[“x”, 1], [“y”, 3]]

no brainer there for a nuby like me :slight_smile:

I think there’s a time limit on describing oneself as a nuby :slight_smile:

but…

conversion fr array to hash… is quite a journey…
[…]
Finally, I got it (dug the archives)…

h2 = Hash[*a]
=> {[“x”, 1]=>[“y”, 3]}

Dig the archives a little more :slight_smile: There’s been a lot of discussion of
this in the past, including a rejected RCR
(RCRS, posted under
‘dave’ due to some glitch but actually submitted by me). I called it
“hashify”, but as you’ll see from the many ruby-talk references it’s
really the to_h[ash] idea.

David

···


David A. Black
dblack@wobblini.net

Hi,

At Sat, 24 Apr 2004 13:05:20 +0900,
Peña, Botp wrote in [ruby-talk:98203]:

I would rather prefer:

h2 = a.to_hash # or a.to_h
{“x”=>1, “y”=>3}

module Enumerable
def to_h
inject({}) {|h, (k, v)| h[k] = v; h}
^^^^^^
^^^^^^
^^^^^^
what’s this?
end
end

-a

···

On Sat, 24 Apr 2004 nobu.nokada@softhome.net wrote:

===============================================================================

EMAIL :: Ara [dot] T [dot] Howard [at] noaa [dot] gov
PHONE :: 303.497.6469
ADDRESS :: E/GC2 325 Broadway, Boulder, CO 80305-3328
URL :: Solar-Terrestrial Physics Data | NCEI
TRY :: for l in ruby perl;do $l -e “print "\x3a\x2d\x29\x0a"”;done
===============================================================================

Ara.T.Howard wrote:

module Enumerable
def to_h
inject({}) {|h, (k, v)| h[k] = v; h}

                  ^^^^^^
                  ^^^^^^
                  ^^^^^^
                  what's this?

inject will get yielded the current state of the result Hash and a new
[key, value] Array. The () syntax lets you access the components of that
Array directly through the variables you use.

This is similar to this assignment:

pair, (key, value) = [“one”, 1], [“two”, 2]
pair # => [“one”, 1]
key # => “two”
value # => 2

This is also explained in the Pickaxe book:
http://www.rubycentral.com/book/tut_expressions.html#UD

Regards,
Florian Gross

···

On Sat, 24 Apr 2004 nobu.nokada@softhome.net wrote:

module Enumerable
def to_h
inject({}) {|h, (k, v)| h[k] = v; h}
^ ^^^^
1 2
1: is the hash that keeps being passed through inject each time.
2: is the key=>value pair, expanding it from a two element array.

I didn’t even realize you could do that type of assignment in a block’s
parameter list, but hey! that’s pretty cool.

I think this should be a standard Array method. There have been many
times I’ve done just this type of thing to get a hash from an array,
for various reasons.

cheers,
–Mark

···

On Apr 23, 2004, at 10:14 PM, Ara.T.Howard wrote:

On Sat, 24 Apr 2004 nobu.nokada@softhome.net wrote:

Hi,

At Sat, 24 Apr 2004 13:05:20 +0900,
Peña, Botp wrote in [ruby-talk:98203]:

I would rather prefer:

h2 = a.to_hash # or a.to_h
{“x”=>1, “y”=>3}

module Enumerable
def to_h
inject({}) {|h, (k, v)| h[k] = v; h}
^^^^^^
^^^^^^
^^^^^^
what’s this?
end
end

Hi,

At Sat, 24 Apr 2004 14:57:09 +0900,
Mark Hubbart wrote in [ruby-talk:98217]:

I didn’t even realize you could do that type of assignment in a block’s
parameter list, but hey! that’s pretty cool.

Block parameter list is equivalent to multiple assignment now,
so you can create new variables there.

···


Nobu Nakada

“Mark Hubbart” discord@mac.com schrieb im Newsbeitrag
news:36BA84AE-95B4-11D8-9D1D-000502FDD5CC@mac.com

Hi,

At Sat, 24 Apr 2004 13:05:20 +0900,
Peña, Botp wrote in [ruby-talk:98203]:

I would rather prefer:

h2 = a.to_hash # or a.to_h
{“x”=>1, “y”=>3}

module Enumerable
def to_h
inject({}) {|h, (k, v)| h[k] = v; h}
^^^^^^
^^^^^^
^^^^^^
what’s this?
end
end

module Enumerable
def to_h
inject({}) {|h, (k, v)| h[k] = v; h}
^ ^^^^
1 2
1: is the hash that keeps being passed through inject each time.
2: is the key=>value pair, expanding it from a two element array.

I didn’t even realize you could do that type of assignment in a block’s
parameter list, but hey! that’s pretty cool.

I think this should be a standard Array method. There have been many
times I’ve done just this type of thing to get a hash from an array,
for various reasons.

There’s one reason why this may not be a standard method: there are at least
two equally reasonable representations of a mapping stored in an array:

Nested arrays as returned by Hash#to_a: [[key1, val1], [key2, val2]]

A sequence: [key1, val1, key2, val2] as used by Hash

Obviously there is no simple way from a Hash to an Array and back to a Hash.
(Btw: is that ever needed? I mean, if you have a hash you can easily create
a copy without an intermediate array.)

So the question is wich representation Enumerable#to_h should expect -
nested or sequence?

robert
···

On Apr 23, 2004, at 10:14 PM, Ara.T.Howard wrote:

On Sat, 24 Apr 2004 nobu.nokada@softhome.net wrote:

Why cannot I simply say?
pair, [key, value] = ["one,1],[“two”,2]
is for arrays, () is for tuples.

Gergo

···

On 0424, Florian Gross wrote:

pair, (key, value) = [“one”, 1], [“two”, 2]
pair # => [“one”, 1]
key # => “two”
value # => 2


±[ Kontra, Gergelykgergely@mcl.hu PhD student Room IB113 ]---------+

http://www.mcl.hu/~kgergely “Olyan langesz vagyok, hogy |
Mobil:(+36 20) 356 9656 ICQ: 175564914 poroltoval kellene jarnom” |
±- Magyar php mirror es magyar php dokumentacio: http://hu.php.net --+

It seems to me that it should be the one that Hash#to_a generates:
nested pairs. They’re already almost a hash anyway; Array has a few
methods for that “format” that allow you to lookup items as if it were
a hash. Why not be able to convert to and from? Makes sense to me.

cheers,
–Mark

···

On Apr 24, 2004, at 2:24 AM, Robert Klemme wrote:

So the question is wich representation Enumerable#to_h should expect -
nested or sequence?

I believe coercion should be as loose less as possible. As a result it
is difficult to imagine that a generic solution is optimal. Only the
actual class knows the optimum. Yet…

One may argue that an Array is a degenerated Hash where the keys are
integer indices. i.e.
[“a”,“b”].to_h() == { 0 => “a”, 1 => “b” }

One may argue that the loose less convertion of a Hash to an Array is
an an array of [key, value]. i.e.
{ 0 => “a”, 1 => “b”}.to_a() == [[0,“a”],[1,“b”]]
(Ruby does that today)

hum… issue is a.to_h().to_a() is quite different from original a.

Better:

What you get when converting a Hash into an Array, see Hash##to_a()

class HashAsArray < Array
def to_h()
# Assume self is an array of [key, value], raise exception if not true
# Error checking code skipped, ToDo: it
Hash[*flatten()]
end
end

What you get when converting an Array into a Hash, see Array##to_h()

class ArrayAsHash < Hash
def to_a()
# Assume keys are integers indices, raise exception if not true
# Error checking code skipped, ToDo: it
super().sort { |(ka,va),(kb,vb)| ka <=> kb }.collect { |(k,v)| v }
# ToDo: There must be a faster solution to do that.
end
end

Now, have Hash.to_a() return an HashAsArray instead of an Array,

and, have Array.to_h() return an ArrayAsHash.

class Hash
alias ruby_to_a to_a
def to_a()
HashAsArray.new().replace( ruby_to_a())
end
def to_h()
self
end
end

class Array
def to_h()
ii = 0
aa =
self.each { |v| aa << (ii += 1); aa << v }
return ArrayAsHash[*aa]
end
end

As a result, an_array.to_h().to_a() is OK and

a_hash.to_a().to_h() is ok too.

p a = [“a”, “b”, “c”, “d”, “e”, “f”]
p h = a.to_h()
p h.class()
p h.kind_of?( Hash)
p h.class() == Hash # not true anymore… but:
case h
when Hash then p “OK”
end
p aa = h.to_a()
p aa.class()
p a.to_h().to_a() == a
p a.to_a().to_h().to_a() == a

p h = { “key_a” => “a”, “key_b” => “b” }
p a = h.to_a()
p a.class()
p a.kind_of?( Array)
p a.class() == Array # not true anymore… but:
case a
when Array then p “OK”
end
p hh = a.to_h()
p hh.class()
p h.to_a().to_h() == h
p h.to_h().to_a().to_h() == h

Most visible change is about these beeing false:

p Array == HashAsArray
p HashAsArray == Array
p Hash == ArrayAsHash
p ArrayAsHash == Hash

Workaround is so ugly that I don’t present it here.

I believe this only change cannot break much existing code,

but very unprobable code that would depend on Hash##to_a()

beeing of class Array precisely. Questionnable

code that does not respect the OO idea of is_a relationship

and test class for equality using == instead of

kind_of? or === (in case statements).

Any drawbacks (beside minor one about .class() == changed) ?

Jean-Hugues

···

At 18:24 24/04/2004 +0900, you wrote:

So the question is wich representation Enumerable#to_h should expect -
nested or sequence?
robert

pair, (key, value) = [“one”, 1], [“two”, 2]
pair # => [“one”, 1]
key # => “two”
value # => 2

Why cannot I simply say?
pair, [key, value] = ["one,1],[“two”,2]
is for arrays, () is for tuples.

Why, yeah, Why ?

In the context of a lvalue (something at the left of
the assignment operator), you must provide a lvalue,
instead of a value.

It is easy to build values, included nested one using
. But only the compiler can build a lvalue.

Probably for historical reasons, the compiler wants
parenthesis within lvalue. And infer the missing
outer ones when it encounter a , before =.

I suppose that the reason is related to the syntax
for formal argument description:
def meth( a, b, c)
end

As a result
def meth( a, [b1,b2], c) looks unbalanced compared to
def meth( a, (b1,b2), c) that Ruby requires.

I guess this is why the later syntax was picked, and
propagated up to the = assignment operator.

Note: That syntax applies for Proc’s parameters too.

I suppose that there is some true value in that syntax,
because, within (), access to variables is by reference,
not by value.

All of this is the result of evolution.
For sure, something like a, = meth() is not as obvious
as (a) = meth() or, better, [a] = meth().

But that’s the way it is, I suppose you have to accept
it.

Yours,

Jean-Hugues

···

At 01:12 29/04/2004 +0900, you wrote:

On 0424, Florian Gross wrote:

Gergo


±[ Kontra, Gergelykgergely@mcl.hu PhD student Room IB113 ]---------+

http://www.mcl.hu/~kgergely “Olyan langesz vagyok, hogy |
Mobil:(+36 20) 356 9656 ICQ: 175564914 poroltoval kellene jarnom” |
±- Magyar php mirror es magyar php dokumentacio: http://hu.php.net --+


Web: http://hdl.handle.net/1030.37/1.1
Phone: +33 (0) 4 92 27 74 17

“Mark Hubbart” discord@mac.com schrieb im Newsbeitrag
news:4DF38309-95D3-11D8-9D1D-000502FDD5CC@mac.com

So the question is wich representation Enumerable#to_h should expect -
nested or sequence?

It seems to me that it should be the one that Hash#to_a generates:
nested pairs. They’re already almost a hash anyway; Array has a few
methods for that “format” that allow you to lookup items as if it were
a hash. Why not be able to convert to and from? Makes sense to me.

If it is a Hash then why don’t you have the data in a hash in the first
place? I mean, the data should not reside in an array if they are to be
used hash-like.

Dunno whether this kind of conversion occurs often. I for my part didn’t
need that till today. Just my 0.02…

robert
···

On Apr 24, 2004, at 2:24 AM, Robert Klemme wrote: