Hash pairs at?

T

Trans

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.
 
W

William James

Trans said:
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}
 
J

Joel VanderWerf

Trans said:
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 }

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?
 
G

gga

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 }
 
G

gga

gga said:
Trans ha escrito:

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
 
D

dblack

Hi --

Trans ha escrito:

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

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

--
Q. What is THE Ruby book for Rails developers?
A. RUBY FOR RAILS by David A. Black (http://www.manning.com/black)
(See what readers are saying! http://www.rubypal.com/r4rrevs.pdf)
Q. Where can I get Ruby/Rails on-site training, consulting, coaching?
A. Ruby Power and Light, LLC (http://www.rubypal.com)
 
P

Phrogz

Trans said:
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
 
P

Phrogz

Phrogz said:
Trans said:
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.
 
D

dblack

Hi --

Phrogz said:
Trans said:
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.

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

--
Q. What is THE Ruby book for Rails developers?
A. RUBY FOR RAILS by David A. Black (http://www.manning.com/black)
(See what readers are saying! http://www.rubypal.com/r4rrevs.pdf)
Q. Where can I get Ruby/Rails on-site training, consulting, coaching?
A. Ruby Power and Light, LLC (http://www.rubypal.com)
 
T

Trans

Robert said:
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.
 
G

gga

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.
 
J

Joel VanderWerf

gga said:
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]]
 
W

William James

Hi --

Phrogz said:
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.

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/

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

dblack

Hi --

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/

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]

That's the idea, though flattenx lets you do flatten_by(n) and also is
written in C for speed.


David

--
Q. What is THE Ruby book for Rails developers?
A. RUBY FOR RAILS by David A. Black (http://www.manning.com/black)
(See what readers are saying! http://www.rubypal.com/r4rrevs.pdf)
Q. Where can I get Ruby/Rails on-site training, consulting, coaching?
A. Ruby Power and Light, LLC (http://www.rubypal.com)
 
D

dblack

Hi --

gga said:
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.


David

--
Q. What is THE Ruby book for Rails developers?
A. RUBY FOR RAILS by David A. Black (http://www.manning.com/black)
(See what readers are saying! http://www.rubypal.com/r4rrevs.pdf)
Q. Where can I get Ruby/Rails on-site training, consulting, coaching?
A. Ruby Power and Light, LLC (http://www.rubypal.com)
 
T

Trans

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.

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.
 
G

gwtmp01

That's the idea, though flattenx lets you do flatten_by(n) and also is
written in C for speed.

I didn't see anyone else mention that in Ruby 1.9...

$ ri-1.9 Array#flatten
---------------------------------------------------------- Array#flatten
array.flatten -> an_array
array.flatten(level) -> an_array
------------------------------------------------------------------------
Returns a new array that is a one-dimensional flattening of this
array (recursively). That is, for every element that is an array,
extract its elements into the new array. If the optional _level_
argument determins the level of recursion to flatten.

Gary Wright
 
D

dblack

Hi --

I didn't see anyone else mention that in Ruby 1.9...

$ ri-1.9 Array#flatten
---------------------------------------------------------- Array#flatten
array.flatten -> an_array
array.flatten(level) -> an_array
------------------------------------------------------------------------
Returns a new array that is a one-dimensional flattening of this
array (recursively). That is, for every element that is an array,
extract its elements into the new array. If the optional _level_
argument determins the level of recursion to flatten.

Cool! I actually didn't know that had made it into 1.9. I look
forward to retiring flattenx :)


David

--
Q. What is THE Ruby book for Rails developers?
A. RUBY FOR RAILS by David A. Black (http://www.manning.com/black)
(See what readers are saying! http://www.rubypal.com/r4rrevs.pdf)
Q. Where can I get Ruby/Rails on-site training, consulting, coaching?
A. Ruby Power and Light, LLC (http://www.rubypal.com)
 

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,755
Messages
2,569,536
Members
45,007
Latest member
obedient dusk

Latest Threads

Top