Project

General

Profile

Feature #13563

Implement Hash#choice method.

Added by babanba-n (matzbara masanao) over 1 year ago. Updated 10 months ago.

Status:
Closed
Priority:
Normal
Assignee:
-
Target version:
-
[ruby-dev:50114]

Description

Hi,

I propose Hash#choice method.

It pick up key and value pairs in Hash like a below code.

{ :a => 1, 2 => "2", "c" => true }.choice(:a, 2) # => { :a => 1, 2 => "2" }
{ :a => 1, 2 => "2", "c" => true }.choice("c", 10000) # => { "c" => true, 10000 => nil }

This method is useful when Hash have many keys, but programer need few key's.

For instance, it pick up personal data in ActiveRecord model's data, and migrate to new device.

feature_phone_user = User.find(params[:src_user_id])
profile = feature_phone_user.attributes.choice(*%i[nickname email sex birthday prefecture])
smart_phone_user   = User.new
smart_phone_user.attributes = profile

In other case, it pick up latest log from http request parameter.

condition = params.to_h.choice("user_id", "service_id")
latest_payment_log = PaymentLog.find_by(condition).last

If this method exist, I guess that many cases change to comfortable just a little.

Please consider about it.

And I write it.
https://github.com/baban/ruby/commit/4014ebe2ae261881669bef8369eb08aaecef2034


Related issues

Related to Ruby trunk - Feature #8499: Importing Hash#slice, Hash#slice!, Hash#except, and Hash#except! from ActiveSupportClosed

History

#1 Updated by babanba-n (matzbara masanao) over 1 year ago

  • Subject changed from Implement Hash#choice mtthod. to Implement Hash#choice method.

#2 [ruby-dev:50115] Updated by shevegen (Robert A. Heiler) over 1 year ago

I am neutral about the suggestion, neither pro or con.

I think the only thing that I want to point out is that .choice() is perhaps not
completely clear. Perhaps .pick() would be better?

We have quite some methods already that allow us to .select() .reject(); and
it also reminds me a bit about .shuffle() and .sample().

I guess this is not the fault of anyone by the way, we just do not have that
many (one-word) english words that are for verbs/actions. So perhaps .choice()
is a good name anyway.

#3 [ruby-dev:50116] Updated by matthewd (Matthew Draper) over 1 year ago

FWIW, ActiveSupport calls this Hash#slice -- http://api.rubyonrails.org/classes/Hash.html#method-i-slice

(With one small behavioural difference: keys not present in the source hash are also omitted from the result, so the second example would return { "c" => true }, not { "c" => true, 10000 => nil }.)

#4 [ruby-dev:50122] Updated by babanba-n (matzbara masanao) over 1 year ago

At first, I overlook Hash#slice method. Sorry...
And, I reconsider about it.

I feel that Hash#slice is wrong name and Hash#pick is better name.
If key is not exist, key omit or return nil.
It is difficult problem.

I think each way have usecase.

For example, below code is return first row.

Item = ItemStock.find_by({}) # return first row 

For that reason, below code have possibility return unintended data.

item = ItemStock.find_by(params.to_h.slice("user_id","item_id")) 
return render { result: "NG" } if item.amount.zero?
item.consume 
render json: { result: "OK" }

So returning nil is more safety.

#5 [ruby-dev:50136] Updated by saturnflyer (Jim Gay) over 1 year ago

babanba-n (matzbara masanao) wrote:

I feel that Hash#slice is wrong name and Hash#pick is better name.
If key is not exist, key omit or return nil.
It is difficult problem.

I prefer Hash#pick over Hash#choice.

I would expect the missing keys to return whatever the default value of the hash is.

hash = Hash.new('foo')
hash[:bar] = 'hello world'

hash.pick(:baz, :bar) #=> {:baz => 'foo', :bar => 'hello world' }

#6 [ruby-dev:50144] Updated by babanba-n (matzbara masanao) over 1 year ago

Thanks reply, saturnflyer.
And I totally agree your propose.

Even if, this porpose is rejected.
I will fix code, and re-push it.

#8 [ruby-dev:50148] Updated by Hanmac (Hans Mackowiak) over 1 year ago

babanba-n (matzbara masanao) wrote:

And, I fix to Hash#pick.

https://github.com/baban/ruby/commit/fa9d1d6291e4507c5fdd997c269cd1cd68003899

in the test case, shouldn't the @h.default= "default" be before the pick?

#10 Updated by mrkn (Kenta Murata) about 1 year ago

  • Related to Feature #8499: Importing Hash#slice, Hash#slice!, Hash#except, and Hash#except! from ActiveSupport added

#11 [ruby-dev:50215] Updated by matz (Yukihiro Matsumoto) about 1 year ago

I vote for Hash#slice that is ActiveSupport compatible.

Matz.

#12 Updated by marcandre (Marc-Andre Lafortune) 10 months ago

  • Status changed from Open to Closed

Also available in: Atom PDF