Project

General

Profile

Actions

Feature #8499

closed

Importing Hash#slice, Hash#slice!, Hash#except, and Hash#except! from ActiveSupport

Added by mrkn (Kenta Murata) over 11 years ago. Updated about 7 years ago.

Status:
Closed
Target version:
[ruby-core:55330]

Description

According to my experiences, the following two idioms often appeare in application codes.

  1. hash = other_hash.select { |k, | [:key1, :key2, :key3].include? k }
  2. hash = other_hash.reject { |k, | [:key1, :key2, :key3].include? k }

On Rails, they can be written in the following forms by using ActiveSupport's features.

  1. hash = other_hash.slice(:key1, :key2, :key3)
  2. hash = other_hash.except(:key1, :key2, :key3)

I think the latter forms are shorter and more readable than the former ones.

So I propose to import the following methods from ActiveSupport:

  • Hash#slice
  • Hash#slice!
  • Hash#except
  • Hash#except!

Files

patch.diff (4.05 KB) patch.diff built-in Hash#slice, Hash#slice!, Hash#except, and Hash#except! Glass_saga (Masaki Matsushita), 07/26/2013 10:58 PM
patch2.diff (4.07 KB) patch2.diff Glass_saga (Masaki Matsushita), 07/29/2013 12:24 PM
patch3.diff (4.04 KB) patch3.diff Glass_saga (Masaki Matsushita), 09/07/2017 10:09 AM
patch4.diff (4.5 KB) patch4.diff Glass_saga (Masaki Matsushita), 09/19/2017 05:41 AM

Related issues 5 (0 open5 closed)

Related to Ruby master - Feature #9108: Hash sub-selectionsClosedmatz (Yukihiro Matsumoto)Actions
Related to Ruby master - Feature #12461: Hash & keys to make subset.RejectedActions
Related to Ruby master - Feature #13563: Implement Hash#choice method.ClosedActions
Related to Ruby master - Feature #15863: Add `Hash#slice!` and `ENV.slice!`RejectedActions
Has duplicate Ruby master - Feature #15822: Add Hash#exceptClosedActions

Updated by zzak (zzak _) over 11 years ago

Hello,

On Thu, Jun 6, 2013 at 4:12 PM, mrkn (Kenta Murata) wrote:

On Rails, they can be written in the following forms by using ActiveSupport's features.

  1. hash = other_hash.slice(:key1, :key2, :key3)
  2. hash = other_hash.reject(:key1, :key2, :key3}

Do you mean "other_hash.except(...)"? There is already Hash#reject

Updated by nobu (Nobuyoshi Nakada) over 11 years ago

  • Description updated (diff)

Updated by mrkn (Kenta Murata) over 11 years ago

zzak (Zachary Scott) wrote:

Hello,

On Thu, Jun 6, 2013 at 4:12 PM, mrkn (Kenta Murata) wrote:

On Rails, they can be written in the following forms by using ActiveSupport's features.

  1. hash = other_hash.slice(:key1, :key2, :key3)
  2. hash = other_hash.reject(:key1, :key2, :key3}

Do you mean "other_hash.except(...)"? There is already Hash#reject

Yes, It's my mistake!

How can I edit the issue description?

Updated by mrkn (Kenta Murata) over 11 years ago

  • Description updated (diff)

I could fix the description.

Updated by nobu (Nobuyoshi Nakada) over 11 years ago

Or enhance the existing methods?

Updated by mrkn (Kenta Murata) over 11 years ago

nobu (Nobuyoshi Nakada) wrote:

Or enhance the existing methods?

I think Hash#[] with the multiple arguments can be an alternative of Hash#slice.

Updated by Anonymous over 11 years ago

+1

Updated by nobu (Nobuyoshi Nakada) over 11 years ago

mrkn (Kenta Murata) wrote:

I think Hash#[] with the multiple arguments can be an alternative of Hash#slice.

Hash#[] should return the values, not the pairs.

Updated by prijutme4ty (Ilya Vorontsov) over 11 years ago

mrkn (Kenta Murata) wrote:

nobu (Nobuyoshi Nakada) wrote:

Or enhance the existing methods?

I think Hash#[] with the multiple arguments can be an alternative of Hash#slice.

There was a proposal (can't find it) to make indexing by multiple arguments to work as nested hashes so that hsh[:a,:b,:c] works as (hsh[:a] && hsh[:a][:b] && hsh[:a][:b][:c]). Your proposal automatically blocks this proposal.

Updated by mrkn (Kenta Murata) over 11 years ago

prijutme4ty (Ilya Vorontsov) wrote:

mrkn (Kenta Murata) wrote:

nobu (Nobuyoshi Nakada) wrote:

Or enhance the existing methods?

I think Hash#[] with the multiple arguments can be an alternative of Hash#slice.

There was a proposal (can't find it) to make indexing by multiple arguments to work as nested hashes so that hsh[:a,:b,:c] works as (hsh[:a] && hsh[:a][:b] && hsh[:a][:b][:c]). Your proposal automatically blocks this proposal.

My proposal primaliry consists of Hash#slice, Hash#except, and bang versions of them.
Hash#[] is optional.

Updated by claytrump (Clay Trump) over 11 years ago

Yay, +1 for slice & except

BTW, makes no sense to me if h[:foo, :bar] returns keys and values in a
hash while h[:foo] returns a value.


<lay trum/>

Updated by mrkn (Kenta Murata) over 11 years ago

On Fri, Jun 7, 2013 at 1:50 AM, Zachary Scott wrote:

Please update description if the proposal has changed (ie: Hash#[])

I mentioned Hash#[] as the reply to nobu's comment #6.
It has not changed my proposal.
My proposal only consists of slice, slice!, except, and except!.

--
Kenta Murata
OpenPGP FP = 1D69 ADDE 081C 9CC2 2E54 98C1 CEFE 8AFB 6081 B062

Updated by nobu (Nobuyoshi Nakada) over 11 years ago

I meant Hash#select and Hash#reject by "the existing methods".

i.e.:

hash = other_hash.select(:key1, :key2, :key3)
hash = other_hash.reject(:key1, :key2, :key3)

But Hash#slice and Hash#except seems fine.

Updated by Glass_saga (Masaki Matsushita) over 11 years ago

How about this implementation?

Updated by matz (Yukihiro Matsumoto) over 11 years ago

The slice method (Array#slice) retrieve "a slice of elements" from an Array.
Considering that, slice is not a good name for the behavior.

So, I prefer Nobu's idea in comment #16

hash = other_hash.select(:key1, :key2, :key3)
hash = other_hash.reject(:key1, :key2, :key3)

Matz

Updated by znz (Kazuhiro NISHIYAMA) over 11 years ago

In attached patch.diff

assert_equal({1=>2, 3=>4}, h.slice!(1, 3))

but ActiveSupport's h.slice!(1, 3) returns {5=>6}.

http://api.rubyonrails.org/classes/Hash.html#method-i-slice-21

Updated by nobu (Nobuyoshi Nakada) over 11 years ago

I've missed the returned values until I've implemented it actually.

  • In ActiveSupport

    • Hash#slice! keeps the given keys and returns removed key/value pairs.
    • Hash#except! removes the given keys and returns self.
  • In this proposal

    • Hash#slice! removes the given keys and returns removed key/value pairs.
    • Hash#except! is same as ActiveSupport.
  • Existing methods

    • Hash#select! keeps the given (by the block) keys and returns self or nil.
    • Hash#reject! removes the given (by the block) keys and returns self or nil.

I don't think changing the result semantics by if any arguments are given is good idea.
What I've thoutht about Hash#slice! was Hash#extract! in ActiveSupport actually.
So what about Hash#extract, Hash#except and those !-versions?

Updated by mrkn (Kenta Murata) over 11 years ago

The attached file is not a part of my proposal. It made by Glass_saga. My proposal is the same as ActiveSupport.

Updated by Glass_saga (Masaki Matsushita) over 11 years ago

I'm sorry for my wrong implementation.
patch2.diff makes Hash#slice! and #except! behave the same as ActiveSupport.
However, I think it isn't good idea to import Hash#slice! and #except! from ActiveSupport as it is.

Because:

  • They returns self if no changes were made. It is inconsistent with other built-in methods like #select! and #reject!.
  • #slice! returns rest of hash, not slice of hash like following. It may be confusing.
hash = {1=>2,3=>4,5=>6}
hash.slice!(1,3) #=> {5,6}
hash #=> {1=>2,3=>4}

Updated by hsbt (Hiroshi SHIBATA) almost 11 years ago

  • Target version changed from 2.1.0 to 2.2.0

Updated by nobu (Nobuyoshi Nakada) over 10 years ago

  • Description updated (diff)

Another name, Hash#only.
http://blog.s21g.com/articles/228

Actions #25

Updated by ko1 (Koichi Sasada) over 9 years ago

Updated by keithrbennett (Keith Bennett) almost 9 years ago

I was about to report this feature request but was happy to find that it was already there...but disappointed that it's been here so long. I'm using Ruby but not Rails and have been needing this functionality a lot lately.

Unless I'm misunderstanding, the implementation of such methods would be trivial. I would much rather see this implemented with a nonoptimal name than not implemented at all.

'slice' and 'except' are ok with me, but if there is a concern about their correctness as names, perhaps they could be 'select_if_key_in' and 'reject_if_key_in'.

But again, anything would be better than nothing.

Actions #27

Updated by shyouhei (Shyouhei Urabe) over 8 years ago

Actions #28

Updated by mrkn (Kenta Murata) about 7 years ago

Updated by Glass_saga (Masaki Matsushita) about 7 years ago

I just rebased it to trunk.

Updated by Glass_saga (Masaki Matsushita) about 7 years ago

Improved implementation and test.
Added documentation.

Updated by knu (Akinori MUSHA) about 7 years ago

One concern is that Array#slice! returns deleted elements whereas this Hash#slice! would return pairs left after slicing.

Updated by mrkn (Kenta Murata) about 7 years ago

  • Status changed from Assigned to Closed

As Hash#slice has been accepted in #13563, I decided to close this issue.
I intend to open the different issue for discussing other methods such as Hash#except.

Thanks.

Actions #33

Updated by nobu (Nobuyoshi Nakada) over 5 years ago

Actions #34

Updated by nobu (Nobuyoshi Nakada) over 5 years ago

Actions

Also available in: Atom PDF

Like0
Like0Like0Like0Like0Like0Like0Like0Like0Like0Like0Like0Like0Like0Like0Like0Like0Like0Like0Like0Like0Like0Like0Like0Like0Like0Like0Like0Like0Like0Like0Like0Like0Like0Like0