Misc #18352
openWhat is the Hash#grep expected?
Description
Current ruby implement, When use Array#grep, the method name means is expected.
[19] pry(#<App>)> [:foo1, :foo2, :bar].grep /foo/
[
:foo1,
:foo2
]
But when use with hash, the result is really confusing ...
[12] pry(#<App>)> {foo: '100', bar: '200'}.grep /foo/
[]
This result almost make Include Enumerable#grep into Hash is totally meaningless, right?
so, i consider if we should introduce a Hash#grep
method instead.
Following is what is expected. (=== is matching on hash key, as Hash#slice)
[20] pry(#<App>)> {foo1: '100', foo2: '200', bar: '200'}.grep /foo/
{
:foo1 => "100",
:foo2 => "200"
}
Updated by zverok (Victor Shepelev) about 3 years ago
This result almost make Include Enumerable#grep into Hash is totally meaningless, right?
Not completely, but close to it :) As grep
accepts anything with #===
, we might imagine some custom useful objects passed, like, IDK....
class HashMatcher < Struct.new(:key, :value, keyword_init: true)
def ===((k, v))
(key.nil? || key === k) && (value.nil? || value === v)
end
end
{foo1: '100', foo2: '200', bar: '200'}.grep(HashMatcher[key: /foo/])
# => [[:foo1, "100"], [:foo2, "200"]]
...but that would be quite an esoteric technique (which I personally never used)
But, considering more useful Hash#grep
, I am not sure I agree with this:
Following is what is expected. (=== is matching on hash key, as Hash#slice)
Why not match only hash value, like, say, Hash#compact
?
{foo1: '100', foo2: '200', bar: '200'}.grep /^1/
# => {foo1: '100'}
{foo1: 100, foo2: 200, bar: 200}.grep(100...150)
# => {foo1: '100'}
I can imagine arguments towards both behaviors saying that they are "natural/useful/expected", and I don't think there is one right answer here actually.
Updated by matheusrich (Matheus Richard) almost 3 years ago
Should we have grep_{keys,values}
?