Hash pairs at?

Seesm like there should be a mehtod for this:

h = { :a=>1, :b=>2, :c=>3 }

h.what_method(:a, :c) #=> { :a=>1, :c=>3 }
^^^^^^^^^^^

Or is there some other simple way we’re supposed to do this?

T.

On 1/20/07, Trans [email protected] wrote:

http://concentrationstudios.com/2006/12/20/12-days-of-stupid-ruby-tricks

Check out Day 11

Trans wrote:

Seesm like there should be a mehtod for this:

h = { :a=>1, :b=>2, :c=>3 }

h.what_method(:a, :c) #=> { :a=>1, :c=>3 }
^^^^^^^^^^^

Or is there some other simple way we’re supposed to do this?

T.

h = { :a,1, :b,2, :c,3 }
==>{:c=>3, :a=>1, :b=>2}
h.reject{|k,v| ![:a,:c].include? k}
==>{:c=>3, :a=>1}

Trans wrote:

h = { :a=>1, :b=>2, :c=>3 }

class Hash
def restrict(*keys)
keys.inject({}) {|h,k| h[k] = self[k]; h}
# alternative:
#Hash[*keys.zip(values_at(*keys)).flatten]
end
end

p h.restrict(:a, :c) #=> { :a=>1, :c=>3 }

Maybe there should be something like this in the core?

On 1/21/07, Trans [email protected] wrote:

T.
I will try to answer your question, but still it will be more
questions :frowning:

Before thinking about the name, naming really is an art, I am thinking
about
the interface

(1) So there is *args as above

(2) Any object responding to #include?

We need two names now, great job Robert :wink:

(1)
#grep, wait a minute hash objects already have grep via Enumerable, no
idea
how it works for hashes though
#filter or filter_keys
#intersect might just be the wrong name
#delete_unless ugly because delete_if takes a block form only
my candidate is
#for_keys

{a=>1, b=>2, c=>3}.for_keys(“hi”, :alpha) => {“hi” => 2} # for some
values of a, b and c :wink:

Now to
(2)
#for_keys_from consistent but long (even ugly)
#keys_from
#intersect
#use_keys
#shadow maybe
a different approach would be to define a method in Enumerable
Enumerable#shadow_hash

[*1…2].shadow_hash {a=>2, b=>3, c=>5, d=>7, e=>11} => {1=>2, 2=>3} #
see
above

this allows even for a call without the accolades.

This all very vague but I feel that such methods would be very useful.

Cheers
Robert

Trans ha escrito:

Seesm like there should be a mehtod for this:

No.

Or is there some other simple way we’re supposed to do this?

T.

[:a, :c].inject({}) { |s, x| s[x] = h[x]; s }

On 1/21/07, Robert D. [email protected] wrote:

On 1/21/07, Trans [email protected] wrote:

STOP PRESS

#pairs_at is much better than anything I came up with, just can’t read
:frowning:

gga wrote:

Trans ha escrito:

Seesm like there should be a mehtod for this:

No.

That being said, Hash DOES seem to be buggy and missing a proper
find_all method.

irb> h.find_all { |k,v| [:a,:c].include?(k) }
=> [[:c, 3], [:a, 1]] # incorrect, it is returning an array, not a
hash

irb> h.reject { |k,v| ![:a,:c].include?(k) }
{:c=>3, :a=>1} # correct

Hi –

On Sun, 21 Jan 2007, gga wrote:

irb> h.find_all { |k,v| [:a,:c].include?(k) }
=> [[:c, 3], [:a, 1]] # incorrect, it is returning an array, not a
hash

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.

It could work otherwise (at least for hashes, though not in the
general Enumerable case), but it works this way by design, not by
accident.

David

Trans wrote:

Seesm like there should be a mehtod for this:

h = { :a=>1, :b=>2, :c=>3 }

h.what_method(:a, :c) #=> { :a=>1, :c=>3 }
^^^^^^^^^^^

h = { :a=>‘a’, :b=>‘b’, :c=>‘c’ }

p h.entries( :a, :c, :d )

#=> { :d=>nil, :a=>‘a’, :c=>‘c’ }

class Hash
def entries( *keys )
self.class[ *keys.zip( values_at( *keys ) ).flatten ]
end
end

Hi –

On Mon, 22 Jan 2007, Phrogz wrote:

with a more elegant, faster implementation than the above. I find this
quite useful sometimes. A recent example that comes to mind is taking
the params hash in Rails and specifying a specific subset of the
populated values to pass on to another method.

I’ll put in a plug here for flattenx, which lets you flatten by any
number of levels so that you could do the above without the
over-flattening vulnerability.

http://raa.ruby-lang.org/project/flattenx/

David

On 1/21/07, gga [email protected] wrote:

T.

[:a, :c].inject({}) { |s, x| s[x] = h[x]; s }

Assuming this is a frequently used idiom you’d not prefer to see
h.pairs_at(:a, :c)
instead of the above?

Astonishes me.

Cheers
Robert

Phrogz wrote:

Trans wrote:

Seems like there should be a mehtod for this:
class Hash
def entries( *keys )
self.class[ *keys.zip( values_at( *keys ) ).flatten ]
end
end

Oh, and yes: I’d like a method like this in the core, also. Preferably
with a more elegant, faster implementation than the above. I find this
quite useful sometimes. A recent example that comes to mind is taking
the params hash in Rails and specifying a specific subset of the
populated values to pass on to another method.

[email protected] wrote:

I’ll put in a plug here for flattenx, which lets you flatten by any
number of levels so that you could do the above without the
over-flattening vulnerability.

http://raa.ruby-lang.org/project/flattenx/

Yes, yes! I’ve used this locally, and wanted to rely on this remotely,
many times!

This, too, should be in the core (particularly since it requires
compilation, and is not a pure-ruby solution.)

Robert D. wrote:

I’d rather see it in the core
I have a slight preference for #pairs_at, #entries is not a bad name, but I
feel the first is more descriptive.

I agree. I think #paris_at is easier to quicky comprehend.

Also, I recalled I had added another method to facets that can do this
too. I was writing Hash#| and thought I should go ahead and wrote an #&
too if reasonable. And lo! There it was:

h = {:a=>1,:b=>2,:c=>3}
h & [:a,:b] #=> {:a=>1,:b=>2}

Code for facets/core/hash/op_and.rb (also op_or.rb):

class Hash
def &(other)
case other
when Array
k = (keys & other)
Hash[*(k.zip(values_at(k)).flatten)]
else
Hash.new[
(to_a & other.to_a).flatten]
end
end

def |(other)
  other.merge self
end

end

Think I still prefer the readability of #pairs_at however. But the
above is good to have too.

T.

On 1/21/07, [email protected] [email protected] wrote:

self.class[ *keys.zip( values_at( *keys ) ).flatten ]

number of levels so that you could do the above without the
over-flattening vulnerability.

http://raa.ruby-lang.org/project/flattenx/

I’d rather see it in the core
I have a slight preference for #pairs_at, #entries is not a bad name,
but I
feel the first is more descriptive.

Cheers
Robert

[email protected] 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.

gga wrote:

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

On 1/21/07, Trans [email protected] wrote:

The more I think about it the more I like the Smalltalk approach, the
syntactic sugar kind of spoils us, ( I remember how happy I was about
C++ in
the first please because I could write
whatever_object + another_object well I was young and stupid than, now
of
course I am older ;).

It is really your posts who brought it up, it is so natural to want to
have
consistent notation.
But sometimes I really think Ruby would be better a language without
Array#<< Proc#[] etc. etc
Why is there not a Array#>> for #pop, these are very reasonable
questions a
new Ruby user will ask!.

If we would have one way to call a proc, one way to push to an array,
things
would be simpler.
I still agree that now, gotten used to it, << is very, very readable
(I
never use #push), but I am starting to wonder if I am not mistaken?

In that spirit I guess #pairs_at is really much more readable, we should
use
Programming Jargon, not Ruby Jargon (although it gives this warm fuzzy
feeling, I agree!!!).

Cheers
Robert

[email protected] wrote:

end
over-flattening vulnerability.

http://raa.ruby-lang.org/project/flattenx/

class Array
def flatten_1
inject([]){|a,x| Array(x).each{|e| a<<e}; a}
end
end

p [[[[22],33],44], %w(aa bb cc), [88,[99,55]], 3.14].flatten_1

— output -----
[[[22], 33], 44, “aa”, “bb”, “cc”, 88, [99, 55], 3.14]