Skip to content

Instantly share code, notes, and snippets.

@O-I
Last active August 2, 2023 17:31
Show Gist options
  • Save O-I/c40d89c4aeb16ae2fc3f to your computer and use it in GitHub Desktop.
Save O-I/c40d89c4aeb16ae2fc3f to your computer and use it in GitHub Desktop.

Revisions

  1. O-I revised this gist Jan 1, 2021. 1 changed file with 1 addition and 3 deletions.
    4 changes: 1 addition & 3 deletions hash_except.md
    Original file line number Diff line number Diff line change
    @@ -1,6 +1,4 @@
    ```diff
    ! Note: As of Ruby 3.0.0, `Hash#except` is now [part][1] of the language. However, Ruby does not implement `Hash#except!`.
    ```
    **Note: As of Ruby 3.0.0, `Hash#except` is now [part][1] of the language. However, Ruby does not implement `Hash#except!`.**

    Sometimes I want to remove a specific key-value pair from a Ruby hash and get the resulting hash back. If you're using Rails or ActiveSupport you can accomplish this using [`Hash#except`](http://api.rubyonrails.org/classes/Hash.html#method-i-except):

  2. O-I revised this gist Jan 1, 2021. 1 changed file with 4 additions and 1 deletion.
    5 changes: 4 additions & 1 deletion hash_except.md
    Original file line number Diff line number Diff line change
    @@ -1,4 +1,6 @@
    **Note: As of Ruby 3.0.0, `Hash#except` is now part of the language. However, Ruby does not implement `Hash#except!`.**
    ```diff
    ! Note: As of Ruby 3.0.0, `Hash#except` is now [part][1] of the language. However, Ruby does not implement `Hash#except!`.
    ```

    Sometimes I want to remove a specific key-value pair from a Ruby hash and get the resulting hash back. If you're using Rails or ActiveSupport you can accomplish this using [`Hash#except`](http://api.rubyonrails.org/classes/Hash.html#method-i-except):

    @@ -59,4 +61,5 @@ hash.tap { |h| [:b, :c].map { |k| h.delete(k) } } # => { d: 4 }
    hash # => { d: 4 }
    ```

    [1]: https://rubyreferences.github.io/rubychanges/3.0.html#hashexcept
    How would you choose to do it?
  3. O-I revised this gist Jan 1, 2021. 1 changed file with 1 addition and 1 deletion.
    2 changes: 1 addition & 1 deletion hash_except.md
    Original file line number Diff line number Diff line change
    @@ -1,4 +1,4 @@
    *As of Ruby 3.0.0, `Hash#except` is now part of the language. However, Ruby does not implement `Hash#except!`.*
    **Note: As of Ruby 3.0.0, `Hash#except` is now part of the language. However, Ruby does not implement `Hash#except!`.**

    Sometimes I want to remove a specific key-value pair from a Ruby hash and get the resulting hash back. If you're using Rails or ActiveSupport you can accomplish this using [`Hash#except`](http://api.rubyonrails.org/classes/Hash.html#method-i-except):

  4. O-I revised this gist Jan 1, 2021. 1 changed file with 2 additions and 0 deletions.
    2 changes: 2 additions & 0 deletions hash_except.md
    Original file line number Diff line number Diff line change
    @@ -1,3 +1,5 @@
    *As of Ruby 3.0.0, `Hash#except` is now part of the language. However, Ruby does not implement `Hash#except!`.*

    Sometimes I want to remove a specific key-value pair from a Ruby hash and get the resulting hash back. If you're using Rails or ActiveSupport you can accomplish this using [`Hash#except`](http://api.rubyonrails.org/classes/Hash.html#method-i-except):

    ```ruby
  5. O-I revised this gist Jan 24, 2015. 1 changed file with 2 additions and 2 deletions.
    4 changes: 2 additions & 2 deletions hash_except.md
    Original file line number Diff line number Diff line change
    @@ -53,8 +53,8 @@ hash.reject! { |k, _| [:b, :c].include? k } # => nil
    hash # => { d: 4 }

    # so maybe tap-map-delete is the best we can do here
    hash.tap { |h| [:b, :c].map { |k| h.delete(k) } } # => { d: 4 }
    hash # => { d: 4 }
    hash.tap { |h| [:b, :c].map { |k| h.delete(k) } } # => { d: 4 }
    hash # => { d: 4 }
    ```

    How would you choose to do it?
  6. O-I revised this gist Jan 24, 2015. 1 changed file with 9 additions and 1 deletion.
    10 changes: 9 additions & 1 deletion hash_except.md
    Original file line number Diff line number Diff line change
    @@ -45,8 +45,16 @@ hash.reject { |k, _| [:b, :c].include? k } # => { d: 4 }
    hash # => { b: 2, c: 3, d: 4 }

    # and, of course, we can also use reject!
    hash.reject { |k, _| [:b, :c].include? k } # => { d: 4 }
    hash.reject! { |k, _| [:b, :c].include? k } # => { d: 4 }
    hash # => { d: 4 }

    # not so fast...reject! doesn't behave the way we want when the keys aren't there :-(
    hash.reject! { |k, _| [:b, :c].include? k } # => nil
    hash # => { d: 4 }

    # so maybe tap-map-delete is the best we can do here
    hash.tap { |h| [:b, :c].map { |k| h.delete(k) } } # => { d: 4 }
    hash # => { d: 4 }
    ```

    How would you choose to do it?
  7. O-I created this gist Jan 24, 2015.
    52 changes: 52 additions & 0 deletions hash_except.md
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,52 @@
    Sometimes I want to remove a specific key-value pair from a Ruby hash and get the resulting hash back. If you're using Rails or ActiveSupport you can accomplish this using [`Hash#except`](http://api.rubyonrails.org/classes/Hash.html#method-i-except):

    ```ruby
    hash = { a: 1, b: 2, c: 3 }
    hash.except(:a) # => { b: 2, c: 3 }

    # note, the original hash is not modified
    hash # => { a: 1, b: 2, c: 3 }

    # it also works with multiple key-value pairs
    hash.except(:a, :c) # => { b: 2 }

    # and returns the original hash if the key doesn't exist
    hash.except(:q) # => { a: 1, b: 2, c: 3 }

    # there's also Hash#except!
    hash.except!(:b) # => { a: 1, c: 3 }

    # this method does modify the original hash
    hash # => { a: 1, c: 3 }

    # and also returns the original hash if the key doesn't exist
    hash.except!(:b) # => { a: 1, c: 3 }
    ```

    Great. But what if we want to do this with plain old Ruby?

    ```ruby
    hash = { a: 1, b: 2, c: 3, d: 4 }

    # the destructive case with removing exactly one key-value pair is easy
    hash.tap { |h| h.delete(:a) } # => { b: 2, c: 3, d: 4 }
    hash # => { b: 2, c: 3, d: 4 }

    # the non-destructive case with one key-value pair isn't much harder
    hash.dup.tap { |h| h.delete(:c) } # => { b: 2, d: 4 }
    hash # => { b: 2, c: 3, d: 4 }

    # but when we want to remove several key-value pairs, it gets a little messy
    hash.dup.tap { |h| [:b, :c].map { |k| h.delete(k) } } # => { d: 4 }
    hash # => { b: 2, c: 3, d: 4 }

    # using reject makes it more palatable
    hash.reject { |k, _| [:b, :c].include? k } # => { d: 4 }
    hash # => { b: 2, c: 3, d: 4 }

    # and, of course, we can also use reject!
    hash.reject { |k, _| [:b, :c].include? k } # => { d: 4 }
    hash # => { d: 4 }
    ```

    How would you choose to do it?