Hash pairs at?

A

Alex LeDonne

Hi --

gga wrote:
(e-mail address removed) wrote:

It's not incorrect or buggy; that's the way Enumerable#find_all works.
In addition to being Enumerables themselves, arrays serve as the
common container for the results of lots of different Enumerables.


Sorry, David, but I disagree. It may not be buggy (as the bugginess is
properly documented :), but it is certainly incorrect. Re-read my
post.
Hash.reject, which is also an Enumerable, DOES return a hash.
Hash.find_all which is algorithmically the same as Hash.reject but
without a negation, does not.
Someone forgot to override find_all in the Hash case, but did remember
to do it for Hash.reject. Or, if you are of the belief that indeed
Enumerables should always return an array, Hash.reject was incorrectly
overridden when it shouldn't have been.

This does look a bit odd...

irb(main):001:0> h = {1=>3, 5=>7}
=> {5=>7, 1=>3}
irb(main):002:0> h.reject {|k,v| k==1}
=> {5=>7}
irb(main):003:0> h.select {|k,v| k==1}
=> [[1, 3]]

A bit. The funny thing, though, is that it of course makes it
possible to do either -- so the irregularity actually provides a kind
of resilience. The consistent version, should it ever come into
being, will shut the door on one of them.

I know that people don't want to do select { not } and so on... so
I can see that it's not really ideal. But it's kind of fascinating
that "fixing" it, in either direction, would result in a net loss of
functionality.

Avoiding net loss, how about going for gross gain. So how about "fixing
it" so there is both?

select
select_pair

And {meth}_pair could also work for assoc arrays too.

T.

Maybe I'm late to the party, but instead of select_pair, I'd name the
method slice, analagous to Array#slice.
 
T

Trans

Joel said:
Looks like the rails crowd has beaten us to it:

http://dev.rubyonrails.org/changeset/5726

It might be in facets, too.

Seems like a good name for a good method.

hmm... in Facets, Hash#slice is just an alias for Hash#values_at.
#slice is a reasonably good name. however I suggested #select_pair, not
as a name for #pairs_at, but as a hash equivalent of #select, to enrich
the langauge with greater polymorphism between hash and asscocivtive
arrays.

{:a=>1, :b=>2}.select{ |k,v| k == :a } #=> [[:a=>1]]
[ [:a, 1], [:b, 2] ].select{ |k,v| k == :a } #=> [[:a=>1]]

{:a=>1, :b=>2}.select_pair{ |k,v| k == :a } #=> { :a=>1 }
[ [:a, 1], [:b, 2] ].select_pair{ |k,v| k == :a } #=> { :a=>1 }

Most of the normal enumerable each-related methods could have hash
equivalents like this.

(I'm not partial to the _pair suffix, but for lack of a better term...)

T.
 
F

Florian Frank

Joel said:
Looks like the rails crowd has beaten us to it:

http://dev.rubyonrails.org/changeset/5726

It might be in facets, too.

Seems like a good name for a good method.

I called it 'extract' and use this:

module HashInclusion
# Extract a hash out of this hash, that only contains key-value pairs
# matching _patterns_ and return it. _patterns_ can be for example /^foo/
# to extract 'foobar' and 'foobaz' or 'foo'/:foo to extract 'foo'.
def extract(*patterns)
patterns.map! { |pat| pat.respond_to?:)match) ? pat : pat.to_s }
result = default_proc ? self.class.new(&default_proc) :
self.class.new(default)
each { |k, v| result[k] = v if patterns.any? { |pat| pat === k.to_s } }
result
end
end

class ::Hash
include HashInclusion
end

The duck typing is a bit fishy, but it's possible to add pattern
objects, that implement #=== and #match this way. Coincidently this is
the case for Regex instances.

It's also interesting, that it's quite difficult to create an empty
"copy" of a given hash in Ruby, without duping and clearing it.
 
K

Ken Bloom

Hi --

gga said:
(e-mail address removed) wrote:

It's not incorrect or buggy; that's the way Enumerable#find_all works.
In addition to being Enumerables themselves, arrays serve as the
common container for the results of lots of different Enumerables.


Sorry, David, but I disagree. It may not be buggy (as the bugginess is
properly documented :), but it is certainly incorrect. Re-read my
post.
Hash.reject, which is also an Enumerable, DOES return a hash.
Hash.find_all which is algorithmically the same as Hash.reject but
without a negation, does not.
Someone forgot to override find_all in the Hash case, but did remember
to do it for Hash.reject. Or, if you are of the belief that indeed
Enumerables should always return an array, Hash.reject was incorrectly
overridden when it shouldn't have been.

This does look a bit odd...

irb(main):001:0> h = {1=>3, 5=>7}
=> {5=>7, 1=>3}
irb(main):002:0> h.reject {|k,v| k==1}
=> {5=>7}
irb(main):003:0> h.select {|k,v| k==1}
=> [[1, 3]]

A bit. The funny thing, though, is that it of course makes it
possible to do either -- so the irregularity actually provides a kind
of resilience. The consistent version, should it ever come into
being, will shut the door on one of them.

I know that people don't want to do select { not } and so on... so
I can see that it's not really ideal. But it's kind of fascinating
that "fixing" it, in either direction, would result in a net loss of
functionality.

No it wouldn't because you could just call .to_a on the returned hash to
get the nested array representation.

--Ken
 
T

Trans

Ken said:
Hi --

gga wrote:
(e-mail address removed) wrote:

It's not incorrect or buggy; that's the way Enumerable#find_all works.
In addition to being Enumerables themselves, arrays serve as the
common container for the results of lots of different Enumerables.


Sorry, David, but I disagree. It may not be buggy (as the bugginess is
properly documented :), but it is certainly incorrect. Re-read my
post.
Hash.reject, which is also an Enumerable, DOES return a hash.
Hash.find_all which is algorithmically the same as Hash.reject but
without a negation, does not.
Someone forgot to override find_all in the Hash case, but did remember
to do it for Hash.reject. Or, if you are of the belief that indeed
Enumerables should always return an array, Hash.reject was incorrectly
overridden when it shouldn't have been.

This does look a bit odd...

irb(main):001:0> h = {1=>3, 5=>7}
=> {5=>7, 1=>3}
irb(main):002:0> h.reject {|k,v| k==1}
=> {5=>7}
irb(main):003:0> h.select {|k,v| k==1}
=> [[1, 3]]

A bit. The funny thing, though, is that it of course makes it
possible to do either -- so the irregularity actually provides a kind
of resilience. The consistent version, should it ever come into
being, will shut the door on one of them.

I know that people don't want to do select { not } and so on... so
I can see that it's not really ideal. But it's kind of fascinating
that "fixing" it, in either direction, would result in a net loss of
functionality.

No it wouldn't because you could just call .to_a on the returned hash to
get the nested array representation.

that's a good point.

the downside however is that we would always have to use #to_a to
ensure polymorphism between assoc array and hash. so it's a bit of an
anti-duck. (array doesn't have a reciporcal #to_h either btw, though
that would be nice in itself!)

T.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,744
Messages
2,569,483
Members
44,903
Latest member
orderPeak8CBDGummies

Latest Threads

Top