Feature #5531
deep_value for dealing with nested hashes
| Status: | Assigned | Start date: | 11/01/2011 | |
|---|---|---|---|---|
| Priority: | Normal | Due date: | ||
| Assignee: | % Done: | 0% |
||
| Category: | - | |||
| Target version: | - |
Description
This feature request stems from dealing with nested hashes, like the params from a request often dealt with in web frameworks.
Conditional code often needs to be written with multiple logical ANDs in order to achieve what this simple function can:
class Hash
def deep_value(*ks)
if ks.size == 1
return self[ks.shift]
else
val = ks.shift
return (self[val].is_a?(Hash) ? self[val].deep_value(*ks) : nil)
end
end
alias dv deep_value
end
deep_value (dv) will simply recurse over a hash given a set of indexes and return the value at the end.
Example:
> foo = {:bar => {:baz => 'blah'}}
> foo.dv(:bar, :baz)
-> 'blah'
> foo.dv(:cats)
-> nil
History
Updated by ko1 (Koichi Sasada) 7 months ago
(2011/11/01 8:52), Kyle Peyton wrote:
> Example:
>
>> foo = {:bar => {:baz => 'blah'}}
>> foo.dv(:bar, :baz)
> -> 'blah'
>> foo.dv(:cats)
> -> nil
Just idea.
How about to extend Hash#[] for it?
--
// SASADA Koichi at atdot dot net
Updated by rkh (Konstantin Haase) 7 months ago
What's the difference (usability wise) between
hash[:foo][:bar]
and
hash.dv(:foo, :bar)
Konstantin
On Oct 31, 2011, at 16:52 , Kyle Peyton wrote:
>
> Issue #5531 has been reported by Kyle Peyton.
>
> ----------------------------------------
> Feature #5531: deep_value for dealing with nested hashes
> http://redmine.ruby-lang.org/issues/5531
>
> Author: Kyle Peyton
> Status: Open
> Priority: Normal
> Assignee:
> Category:
> Target version:
>
>
> This feature request stems from dealing with nested hashes, like the params from a request often dealt with in web frameworks.
>
> Conditional code often needs to be written with multiple logical ANDs in order to achieve what this simple function can:
>
> class Hash
> def deep_value(*ks)
> if ks.size
Updated by rkh (Konstantin Haase) 7 months ago
What's the difference (usability wise) between
hash[:foo][:bar]
and
hash.dv(:foo, :bar)
Konstantin
On Oct 31, 2011, at 16:52 , Kyle Peyton wrote:
>
> Issue #5531 has been reported by Kyle Peyton.
>
> ----------------------------------------
> Feature #5531: deep_value for dealing with nested hashes
> http://redmine.ruby-lang.org/issues/5531
>
> Author: Kyle Peyton
> Status: Open
> Priority: Normal
> Assignee:
> Category:
> Target version:
>
>
> This feature request stems from dealing with nested hashes, like the params from a request often dealt with in web frameworks.
>
> Conditional code often needs to be written with multiple logical ANDs in order to achieve what this simple function can:
>
> class Hash
> def deep_value(*ks)
> if ks.size
Updated by rkh (Konstantin Haase) 7 months ago
Never mind, got it.
On Oct 31, 2011, at 17:32 , Haase, Konstantin wrote:
> What's the difference (usability wise) between
>
> hash[:foo][:bar]
>
> and
>
> hash.dv(:foo, :bar)
>
> Konstantin
>
> On Oct 31, 2011, at 16:52 , Kyle Peyton wrote:
>
>>
>> Issue #5531 has been reported by Kyle Peyton.
>>
>> ----------------------------------------
>> Feature #5531: deep_value for dealing with nested hashes
>> http://redmine.ruby-lang.org/issues/5531
>>
>> Author: Kyle Peyton
>> Status: Open
>> Priority: Normal
>> Assignee:
>> Category:
>> Target version:
>>
>>
>> This feature request stems from dealing with nested hashes, like the params from a request often dealt with in web frameworks.
>>
>> Conditional code often needs to be written with multiple logical ANDs in order to achieve what this simple function can:
>>
>> class Hash
>> def deep_value(*ks)
>> if ks.size
Updated by Eregon (Benoit Daloze) 7 months ago
On 1 November 2011 01:26, SASADA Koichi <ko1@atdot.net> wrote:
> (2011/11/01 8:52), Kyle Peyton wrote:
>> Example:
>>
>>> foo = {:bar => {:baz => 'blah'}}
>>> foo.dv(:bar, :baz)
>> -> 'blah'
>>> foo.dv(:cats)
>> -> nil
>
> Just idea.
> How about to extend Hash#[] for it?
>
> --
> // SASADA Koichi at atdot dot net
That would be nice.
Updated by alexeymuranov (Alexey Muranov) 7 months ago
Konstantin Haase wrote:
> Never mind, got it.
>
> On Oct 31, 2011, at 17:32 , Haase, Konstantin wrote:
>
> > What's the difference (usability wise) between
> >
> > hash[:foo][:bar]
> >
> > and
> >
> > hash.dv(:foo, :bar)
> >
> > Konstantin
I'll answer anyway if someone else didn't get it :).
{ :foo => 1 }[2][3] raises NoMethodError, and { :foo => 1 }.dv(2,3) or { :foo => 1 }[2,3] should return nil.
Update: also it is possible to keep the list of all arguments in a single variable and call { :foo => 1 }.dv(*args)
Updated by alexeymuranov (Alexey Muranov) 7 months ago
I can think of the following questions/objections to the suggested method definition:
1. is `{ 1 => 2}.dv(1,1) # => nil` the desired result?
2. this method examines the (super)class name of an object, rather than the behavior of an object, so does not allow to mix nested hashes and arrays,
3. this method calls itself recursively, while a loop would suffice.
The following is not a serious suggestion, but seriously, how about:
class Object
def deep_value(*keys)
obj = self
obj = obj[keys.shift] while !keys.empty? && obj.respond_to?(:[])
return obj
end
end
(For this to work well it will be important to call it #deep_value and not to redefine #[].)
---
Update. Another suggestion, probably a better one (at least simpler):
class Object
def deep_value(*keys)
obj = self
obj = obj[keys.shift] until keys.empty? || obj.nil?
return obj
end
end
Updated by nobu (Nobuyoshi Nakada) 7 months ago
What about:
class Hash
def [](*keys)
keys.inject(self) {|container, key| container.fetch(key) {return}}
end
end
Updated by alexeymuranov (Alexey Muranov) 7 months ago
Nobuyoshi Nakada wrote:
> =begin
> What about:
>
> class Hash
> def [](*keys)
> keys.inject(self) {|container, key| container.fetch(key) {return}}
> end
> end
> =end
Just a small remark about defining this exclusively for Hash: what if some of the values is not a Hash but responds to #fetch? (will not look consistent enough to me).
Updated by trans (Thomas Sawyer) 7 months ago
Probably best to use #[] internally too.
class Hash
def [](*keys)
keys.inject(self) {|container, key| value = container[key]; value ? value : return value}
end
end
@Alexey you may have a point. But I suspect it would need to be conditioned off of responding to #to_h or #to_hash instead of using `is_a?(Hash)`.
Updated by neleai (Ondrej Bilka) 7 months ago
Do you need hash or something like multidimensional hash class that uses [], each iterates on nested...
On Sun, Nov 06, 2011 at 05:48:52PM +0900, Thomas Sawyer wrote:
>
> Issue #5531 has been updated by Thomas Sawyer.
>
>
> Probably best to use #[] internally too.
>
> class Hash
> def [](*keys)
> keys.inject(self) {|container, key| value = container[key]; value ? value : return value}
> end
> end
>
> @Alexey you may have a point. But I suspect it would need to be conditioned off of responding to #to_h or #to_hash instead of using `is_a?(Hash)`.
>
> ----------------------------------------
> Feature #5531: deep_value for dealing with nested hashes
> http://redmine.ruby-lang.org/issues/5531
>
> Author: Kyle Peyton
> Status: Open
> Priority: Normal
> Assignee:
> Category:
> Target version:
>
>
> This feature request stems from dealing with nested hashes, like the params from a request often dealt with in web frameworks.
>
> Conditional code often needs to be written with multiple logical ANDs in order to achieve what this simple function can:
>
> class Hash
> def deep_value(*ks)
> if ks.size == 1
> return self[ks.shift]
> else
> val = ks.shift
> return (self[val].is_a?(Hash) ? self[val].deep_value(*ks) : nil)
> end
> end
>
> alias dv deep_value
> end
>
>
> deep_value (dv) will simply recurse over a hash given a set of indexes and return the value at the end.
>
> Example:
>
> > foo = {:bar => {:baz => 'blah'}}
> > foo.dv(:bar, :baz)
> -> 'blah'
> > foo.dv(:cats)
> -> nil
>
>
>
> --
> http://redmine.ruby-lang.org
--
network packets travelling uphill (use a carrier pigeon)
Updated by mame (Yusuke Endoh) about 1 month ago
- Status changed from Open to Assigned
- Assignee set to matz (Yukihiro Matsumoto)
Updated by weexpectedTHIS (Kyle Peyton) about 1 month ago
What's the status of this issue? Good idea? Bad idea?