Web Images Videos Maps News Shopping Gmail more »
Recently Visited Groups | Help | Sign in
Google Groups Home
No Keys, nor other hash methods on multidimensional hash
There are currently too many topics in this group that display first. To make this topic appear first, remove this option from another topic.
There was an error processing your request. Please try again.
flag
  17 messages - Collapse all  -  Translate all to Translated (View all originals)
The group you are posting to is a Usenet group. Messages posted to this group will make your email address visible to anyone on the Internet.
Your reply message has not been sent.
Your post was successful
 
From:
To:
Cc:
Followup To:
Add Cc | Add Followup-to | Edit Subject
Subject:
Validation:
For verification purposes please type the characters you see in the picture below or the numbers you hear by clicking the accessibility icon. Listen and type the numbers you hear
 
Xeno Campanoli  
View profile  
 More options Aug 22 2005, 3:14 pm
Newsgroups: comp.lang.ruby
From: Xeno Campanoli <x...@eskimo.com>
Date: Tue, 23 Aug 2005 04:14:16 +0900
Local: Mon, Aug 22 2005 3:14 pm
Subject: No Keys, nor other hash methods on multidimensional hash
Okay, I'm taking the example I got last week for multi-dimensional hashes, and
I don't have access to any Hash methods:

pHash = lambda { Hash.new {|h,k| h[k] = pHash.call }
pHash['1']['a'] = "one"
p pHash.keys

I run this and get the result:

..undefined method `keys' for ... (NoMethodError)

Do I need to dereference or something, or is this just something that doesn't
work after all?

Sincerely, Xeno Campanoli, Ruby neophyte and general paraphernalian.


    Reply to author    Forward  
You must Sign in before you can post messages.
To post a message you must first join this group.
Please update your nickname on the subscription settings page before posting.
You do not have the permission required to post.
David A. Black  
View profile  
(1 user)  More options Aug 22 2005, 3:29 pm
Newsgroups: comp.lang.ruby
From: "David A. Black" <dbl...@wobblini.net>
Date: Tue, 23 Aug 2005 04:29:44 +0900
Local: Mon, Aug 22 2005 3:29 pm
Subject: Re: No Keys, nor other hash methods on multidimensional hash
Hi --

On Tue, 23 Aug 2005, Xeno Campanoli wrote:
> Okay, I'm taking the example I got last week for multi-dimensional hashes, and
> I don't have access to any Hash methods:

> pHash = lambda { Hash.new {|h,k| h[k] = pHash.call }
> pHash['1']['a'] = "one"
> p pHash.keys

> I run this and get the result:

> ...undefined method `keys' for ... (NoMethodError)

> Do I need to dereference or something, or is this just something that doesn't
> work after all?

Try this:

   hash_lambda = lambda { Hash.new {|h,k| h[k] = hash_lambda.call } }
   hash = hash_lambda[]
   hash['1']['a'] = "one"
   p hash.keys

David

--
David A. Black
dbl...@wobblini.net


    Reply to author    Forward  
You must Sign in before you can post messages.
To post a message you must first join this group.
Please update your nickname on the subscription settings page before posting.
You do not have the permission required to post.
Martin DeMello  
View profile  
 More options Aug 22 2005, 3:36 pm
Newsgroups: comp.lang.ruby
From: Martin DeMello <martindeme...@yahoo.com>
Date: Mon, 22 Aug 2005 19:36:10 GMT
Local: Mon, Aug 22 2005 3:36 pm
Subject: Re: No Keys, nor other hash methods on multidimensional hash

Xeno Campanoli <x...@eskimo.com> wrote:
> Okay, I'm taking the example I got last week for multi-dimensional hashes, and
> I don't have access to any Hash methods:

> pHash = lambda { Hash.new {|h,k| h[k] = pHash.call }

lambda creates an anonymous function, which in this case returns a hash.
hash_factory might have been a better variable name:

hash_factory = lambda { Hash.new {|h,k| h[k] = hash_factory.call }}

How it works: Hash.new {|h,k| block} creates a new hash, and calls the
block whenever the hash is called with a nonexistent key. h and k, the
two parameters passed to the block, are the hash itself and the key you
tried to look up.

lambda {Hash.new} creates an anonymous function that returns a hash. The
clever part here is that we capture a reference to the function we're
defining, and pass that reference into the block we pass to the hash
(this all works because lambdas are lazily evaluated). So now every time
we call the hash with a missing key, the hash_factory is called again
and generates a new autovivifying hash to store as the value.

Here's how you use it:

hash = hash_factory.call
hash[1][2][3] #=> nil, but the hash will now have the keys

martin


    Reply to author    Forward  
You must Sign in before you can post messages.
To post a message you must first join this group.
Please update your nickname on the subscription settings page before posting.
You do not have the permission required to post.
Bill Kelly  
View profile  
 More options Aug 22 2005, 3:39 pm
Newsgroups: comp.lang.ruby
From: "Bill Kelly" <bi...@cts.com>
Date: Tue, 23 Aug 2005 04:39:22 +0900
Local: Mon, Aug 22 2005 3:39 pm
Subject: Re: No Keys, nor other hash methods on multidimensional hash
Hi,

From: "Xeno Campanoli" <x...@eskimo.com>

> Okay, I'm taking the example I got last week for multi-dimensional hashes, and
> I don't have access to any Hash methods:

> pHash = lambda { Hash.new {|h,k| h[k] = pHash.call }
> pHash['1']['a'] = "one"
> p pHash.keys

> I run this and get the result:

> ...undefined method `keys' for ... (NoMethodError)

> Do I need to dereference or something, or is this just something that doesn't
> work after all?

pHash isn't the hash-of-hashes itself, it's a Proc object
that knows how to create such a hash.

in irb:

>> pHash = lambda { Hash.new {|h,k| h[k] = pHash.call } }

=> #<Proc:0x02dc4960@(irb):1>
>> pHash.class  # we can see its class is Proc
=> Proc
>> pHash.call   # if we call the Proc, it does its job and creates the hash
=> {}
>> pHash[]      # this is just a synonym for pHash.call

=> {}

I guess one could look at "pHash" as a factory that creates
an auto-vivifying hash.

Regards,

Bill


    Reply to author    Forward  
You must Sign in before you can post messages.
To post a message you must first join this group.
Please update your nickname on the subscription settings page before posting.
You do not have the permission required to post.
Phrogz  
View profile  
 More options Aug 22 2005, 5:16 pm
Newsgroups: comp.lang.ruby
From: "Phrogz" <ga...@refinery.com>
Date: 22 Aug 2005 14:16:57 -0700
Local: Mon, Aug 22 2005 5:16 pm
Subject: Re: No Keys, nor other hash methods on multidimensional hash
To be clear, what Bill is saying is that you need to use pHash.call to
create your hash, and call the Hash methods on that. Like so:

pHash = lambda { Hash.new {|h,k| h[k] = pHash.call } }

uberhash = pHash.call

uberhash['L']['a'] = "one"
p uberhash.keys        #=> ["L"]
p uberhash['L'].keys   #=> ["a"]
p uberhash['L'].values #=> ["one"]


    Reply to author    Forward  
You must Sign in before you can post messages.
To post a message you must first join this group.
Please update your nickname on the subscription settings page before posting.
You do not have the permission required to post.
William James  
View profile  
 More options Aug 22 2005, 5:56 pm
Newsgroups: comp.lang.ruby
From: "William James" <w_a_x_...@yahoo.com>
Date: 22 Aug 2005 14:56:01 -0700
Local: Mon, Aug 22 2005 5:56 pm
Subject: Re: No Keys, nor other hash methods on multidimensional hash

Phrogz wrote:
> To be clear, what Bill is saying is that you need to use pHash.call to
> create your hash, and call the Hash methods on that. Like so:

> pHash = lambda { Hash.new {|h,k| h[k] = pHash.call } }

> uberhash = pHash.call

> uberhash['L']['a'] = "one"
> p uberhash.keys        #=> ["L"]
> p uberhash['L'].keys   #=> ["a"]
> p uberhash['L'].values #=> ["one"]

How would you test to see if this exists?

h[9][8][7][6][5][4][3][2][1]


    Reply to author    Forward  
You must Sign in before you can post messages.
To post a message you must first join this group.
Please update your nickname on the subscription settings page before posting.
You do not have the permission required to post.
David A. Black  
View profile  
 More options Aug 22 2005, 5:59 pm
Newsgroups: comp.lang.ruby
From: "David A. Black" <dbl...@wobblini.net>
Date: Tue, 23 Aug 2005 06:59:33 +0900
Local: Mon, Aug 22 2005 5:59 pm
Subject: Re: No Keys, nor other hash methods on multidimensional hash
Hi --

I think it exists as soon as you refer to it.  (I thought that's the
whole point :-)  But if you didn't want that to happen I guess you
could do:

   if h[9][8][7][6][5][4][3][2].has_key?(1) ...

David

--
David A. Black
dbl...@wobblini.net


    Reply to author    Forward  
You must Sign in before you can post messages.
To post a message you must first join this group.
Please update your nickname on the subscription settings page before posting.
You do not have the permission required to post.
William James  
View profile  
 More options Aug 22 2005, 6:25 pm
Newsgroups: comp.lang.ruby
From: "William James" <w_a_x_...@yahoo.com>
Date: 22 Aug 2005 15:25:50 -0700
Local: Mon, Aug 22 2005 6:25 pm
Subject: Re: No Keys, nor other hash methods on multidimensional hash

It's not the whole point. One needs to be able to check
to see if an entry exists without changing the hash.

irb(main):002:0> h=pHash.call
=> {}
irb(main):003:0> h['foo']=999
=> 999
irb(main):005:0> if h[9][8][7][6][5][4][3][2].has_key?(1) then puts
'ok';end
=> nil
irb(main):006:0> p h
{"foo"=>999, 9=>{8=>{7=>{6=>{5=>{4=>{3=>{2=>{}}}}}}}}}

Even lowly Awk can easily do this.
-------------------------------------------------
BEGIN {
  a[9,8,7,6,5,4,3,2,1] = "yes"
  if ( (9,8,7,6,5,4,3,2,1) in a )
    print "o.k."
  if ( (0,8,7,6,5,4,3,2,1) in a )
    print "not o.k."
  if ( (0,8,7,6,5,4,3,2) in a )
    print "not o.k."
  print length(a)

}

-------------------------------------------------
Output:

o.k.
1


    Reply to author    Forward  
You must Sign in before you can post messages.
To post a message you must first join this group.
Please update your nickname on the subscription settings page before posting.
You do not have the permission required to post.
David A. Black  
View profile  
 More options Aug 22 2005, 6:56 pm
Newsgroups: comp.lang.ruby
From: "David A. Black" <dbl...@wobblini.net>
Date: Tue, 23 Aug 2005 07:56:51 +0900
Local: Mon, Aug 22 2005 6:56 pm
Subject: Re: No Keys, nor other hash methods on multidimensional hash
Hi --

I can't tell if you're saying the has_key? thing was the right
solution or that it wasn't :-)  The creation of the intermediate
hashes is desired, right?

David

--
David A. Black
dbl...@wobblini.net


    Reply to author    Forward  
You must Sign in before you can post messages.
To post a message you must first join this group.
Please update your nickname on the subscription settings page before posting.
You do not have the permission required to post.
William James  
View profile  
 More options Aug 22 2005, 7:52 pm
Newsgroups: comp.lang.ruby
From: "William James" <w_a_x_...@yahoo.com>
Date: 22 Aug 2005 16:52:06 -0700
Local: Mon, Aug 22 2005 7:52 pm
Subject: Re: No Keys, nor other hash methods on multidimensional hash

Quote:
One needs to be able to check to see if an entry exists without
changing the hash.

Creating intermediate hashes changes the hash.

Therefore, it wasn't the right solution.

The Awk example shows that Awk can perform this check without
altering the hash in any way whatsoever, just as  h.key?('foo')
doesn't alter the hash.  Having to alter the hash whenever you
check for the existence of a key would be extremely crude and
ineffecient.


    Reply to author    Forward  
You must Sign in before you can post messages.
To post a message you must first join this group.
Please update your nickname on the subscription settings page before posting.
You do not have the permission required to post.
Florian Groß  
View profile  
 More options Aug 22 2005, 8:01 pm
Newsgroups: comp.lang.ruby
From: Florian Groß <flor...@gmail.com>
Date: Tue, 23 Aug 2005 09:01:23 +0900
Local: Mon, Aug 22 2005 8:01 pm
Subject: Re: No Keys, nor other hash methods on multidimensional hash

Xeno Campanoli wrote:
> Okay, I'm taking the example I got last week for multi-dimensional hashes, and
> I don't have access to any Hash methods:

> pHash = lambda { Hash.new {|h,k| h[k] = pHash.call }
> pHash['1']['a'] = "one"
> p pHash.keys

> I run this and get the result:

> ...undefined method `keys' for ... (NoMethodError)

Try this one instead:

hash_proc = lambda { |hash, key| hash[key] = Hash.new(&hash_proc) }
hash = Hash.new(&hash_proc)

> irb(main):003:0> hash[5][4][3][2][1] = 0
> => 0
> irb(main):004:0> hash.keys
> => [5]
> irb(main):005:0> hash
> => {5=>{4=>{3=>{2=>{1=>0}}}}}

Or if you're a fan of the y combinator:

class Proc
   def self.y(&block)
     result = lambda { |*args| block.call(result, *args) }
   end
end

Hash.new(&Proc.y { |p, h, k| h[k] = Hash.new(&p) })


    Reply to author    Forward  
You must Sign in before you can post messages.
To post a message you must first join this group.
Please update your nickname on the subscription settings page before posting.
You do not have the permission required to post.
James Edward Gray II  
View profile  
 More options Aug 22 2005, 8:22 pm
Newsgroups: comp.lang.ruby
From: James Edward Gray II <ja...@grayproductions.net>
Date: Tue, 23 Aug 2005 09:22:59 +0900
Local: Mon, Aug 22 2005 8:22 pm
Subject: Re: No Keys, nor other hash methods on multidimensional hash
On Aug 22, 2005, at 5:26 PM, William James wrote:

> It's not the whole point. One needs to be able to check
> to see if an entry exists without changing the hash.

> irb(main):002:0> h=pHash.call
> => {}
> irb(main):003:0> h['foo']=999
> => 999
> irb(main):005:0> if h[9][8][7][6][5][4][3][2].has_key?(1) then puts
> 'ok';end
> => nil
> irb(main):006:0> p h
> {"foo"=>999, 9=>{8=>{7=>{6=>{5=>{4=>{3=>{2=>{}}}}}}}}}

I'm not sure what you're trying to show here???

You called has_key?() on the last Hash.  It did not add that key to  
the Hash, just as you said it shouldn't.  The other Hashes were  
autovivified along the way, because you wrote code to make it so.  I  
would be disappointed if any of the above had behaved differently and  
I know at least Perl has identical behavior.

That said, if you want an object that can check many levels deep  
without creating the upper levels, you can surely code one up with  
little effort.

James Edward Gray II


    Reply to author    Forward  
You must Sign in before you can post messages.
To post a message you must first join this group.
Please update your nickname on the subscription settings page before posting.
You do not have the permission required to post.
David A. Black  
View profile  
 More options Aug 22 2005, 8:24 pm
Newsgroups: comp.lang.ruby
From: "David A. Black" <dbl...@wobblini.net>
Date: Tue, 23 Aug 2005 09:24:53 +0900
Local: Mon, Aug 22 2005 8:24 pm
Subject: Re: No Keys, nor other hash methods on multidimensional hash

It wasn't clear to me which hash you meant.  I interpreted it as
.....[2], and checking its keys was a way of checking the existence
of the entry without changing the hash (i.e., *that* hash).

I do think the original impetus for this whole thing was the creation
of a hash that automatically filled in with hashes in the face of
h[1][2][3]....  It's probably significantly harder to make a hash that
does that sometimes, but not always, as it were.  I haven't tried it
yet though.

David

--
David A. Black
dbl...@wobblini.net


    Reply to author    Forward  
You must Sign in before you can post messages.
To post a message you must first join this group.
Please update your nickname on the subscription settings page before posting.
You do not have the permission required to post.
William James  
View profile  
 More options Aug 22 2005, 8:31 pm
Newsgroups: comp.lang.ruby
From: "William James" <w_a_x_...@yahoo.com>
Date: 22 Aug 2005 17:31:57 -0700
Local: Mon, Aug 22 2005 8:31 pm
Subject: Re: No Keys, nor other hash methods on multidimensional hash

Here's one way, but it doesn't seem efficient:
------------------------------------------------------------------
class Hash
  def has( *subs )
    h=self
    subs.each{|x|
      return false unless h.key?(x)
      h=h[x]
    }
    true
  end
end

pHash = lambda { Hash.new {|h,k| h[k] = pHash.call } }

uberhash = pHash.call

uberhash['a']['b']['c']='The crux.'
p uberhash.has('a','b','c')
p uberhash.has('a','b','x')
p uberhash
------------------------------------------------------------------

Output:

true
false
{"a"=>{"b"=>{"c"=>"The crux."}}}

Note that the hash wasn't changed by the check for the
nonexistent key.

By the way, here's how Awk effortlessly handles multidimensional
associative arrays (hashes):
   a['foo','bar']
is equivalent to
   a['foo' SUBSEP 'bar']
The keys are merely joined using a character that won't be found
in the keys.


    Reply to author    Forward  
You must Sign in before you can post messages.
To post a message you must first join this group.
Please update your nickname on the subscription settings page before posting.
You do not have the permission required to post.
David A. Black  
View profile  
 More options Aug 22 2005, 9:00 pm
Newsgroups: comp.lang.ruby
From: "David A. Black" <dbl...@wobblini.net>
Date: Tue, 23 Aug 2005 10:00:44 +0900
Local: Mon, Aug 22 2005 9:00 pm
Subject: Re: No Keys, nor other hash methods on multidimensional hash
Hi --

On Tue, 23 Aug 2005, William James wrote:
> By the way, here's how Awk effortlessly handles multidimensional
> associative arrays (hashes):
>   a['foo','bar']
> is equivalent to
>   a['foo' SUBSEP 'bar']
> The keys are merely joined using a character that won't be found
> in the keys.

Am I right that the keys can only be scalar values?

David

--
David A. Black
dbl...@wobblini.net


    Reply to author    Forward  
You must Sign in before you can post messages.
To post a message you must first join this group.
Please update your nickname on the subscription settings page before posting.
You do not have the permission required to post.
William James  
View profile  
 More options Aug 24 2005, 12:37 pm
Newsgroups: comp.lang.ruby
From: "William James" <w_a_x_...@yahoo.com>
Date: 24 Aug 2005 09:37:20 -0700
Local: Wed, Aug 24 2005 12:37 pm
Subject: Re: No Keys, nor other hash methods on multidimensional hash

David A. Black wrote:
> Hi --

> On Tue, 23 Aug 2005, William James wrote:

> > By the way, here's how Awk effortlessly handles multidimensional
> > associative arrays (hashes):
> >   a['foo','bar']
> > is equivalent to
> >   a['foo' SUBSEP 'bar']
> > The keys are merely joined using a character that won't be found
> > in the keys.

> Am I right that the keys can only be scalar values?

Yes.  The method is crude, but effective.

Getting back to checking for existence of a key in an
autovivifying hash; what if I check for a million keys
that don't exist:

1_000_000.times { |i|
   if h[i][8][7][6][5][4][3][2].has_key?(1) ...

}

This causes the hash to grow to enormous size.  Will the
garbage-collector
eventually remove the spurious entries?

    Reply to author    Forward  
You must Sign in before you can post messages.
To post a message you must first join this group.
Please update your nickname on the subscription settings page before posting.
You do not have the permission required to post.
Martin DeMello  
View profile  
 More options Aug 25 2005, 3:04 am
Newsgroups: comp.lang.ruby
From: Martin DeMello <martindeme...@yahoo.com>
Date: Thu, 25 Aug 2005 07:04:17 GMT
Local: Thurs, Aug 25 2005 3:04 am
Subject: Re: No Keys, nor other hash methods on multidimensional hash

William James <w_a_x_...@yahoo.com> wrote:

> Getting back to checking for existence of a key in an
> autovivifying hash; what if I check for a million keys
> that don't exist:

> 1_000_000.times { |i|
>    if h[i][8][7][6][5][4][3][2].has_key?(1) ...
> }

> This causes the hash to grow to enormous size.  Will the
> garbage-collector eventually remove the spurious entries?

How can it? There's nothing to distinguish 'spurious' entries from
'real' ones - that's the whole point of autovivification.

That would make a cute quiz/golf problem, though - given such an
autovivified hash, write a .cleanup! method that recursively deletes any
keys that point to nil.

martin


    Reply to author    Forward  
You must Sign in before you can post messages.
To post a message you must first join this group.
Please update your nickname on the subscription settings page before posting.
You do not have the permission required to post.
End of messages
« Back to Discussions « Newer topic     Older topic »

Create a group - Google Groups - Google Home - Terms of Service - Privacy Policy
©2009 Google