From: naruse@... Date: 2018-02-04T13:05:34+00:00 Subject: [ruby-dev:50467] [Ruby trunk Feature#14417] String#sub / String#gsub に『キーが Symbol の Hash』を渡せるようにする提案 Issue #14417 has been updated by naruse (Yui NARUSE). Hanmac (Hans Mackowiak) wrote: > @duerst: what about my example where it does transform the keye internal for the given Hash? > or is that a nono too? > it might be possible to only do it if the given hash has non String key? If the hash is called many times from gsub, those integers shold be converted as String before gsub. Because such conversion needs object allocation many times, and cause many GC. I think ``` h = {1 => "A", 2 => "B", 3 => "C", 4 => "D", 5 => "E"} "12345".gsub(/\d/){ h[$&.to_i] } ``` is faster than such code. ---------------------------------------- Feature #14417: String#sub / String#gsub に『キーが Symbol の Hash』を渡せるようにする提案 https://bugs.ruby-lang.org/issues/14417#change-70157 * Author: osyo (manga osyo) * Status: Feedback * Priority: Normal * Assignee: * Target version: ---------------------------------------- ## 概要 `String#sub` / `String#gsub` に『キーが `Symbol` の `Hash`』を渡した場合でも `String` の場合と同様に置き換える。 ## 現行の動作 ```ruby hash = {'b'=>'B', 'c'=>'C'} p "abcabc".gsub(/[bc]/, hash) #=> "aBCaBC" # キー が Symbol の Hash は置き換えられない hash = { b: 'B', c: 'C' } p "abcabc".gsub(/[bc]/, hash) #=> "aa" # キー が Symbol の Hash は String に変換する必要がある p "abcabc".gsub(/[bc]/, hash.transform_keys(&:to_s)) #=> "aBCaBC" ``` ## 提案する動作 ```ruby # キーが String の場合は現行維持 hash = {'b'=>'B', 'c'=>'C'} p "abcabc".gsub(/[bc]/, hash) #=> "aBCaBC" hash = { b: 'B', c: 'C' } # $& は動的であるべきなので String のまま p "abcabc".gsub(/[bc]/){hash[$&]} #=> "aa" # ブロックの引数は動的であるべきなので String のまま p "abcabc".gsub(/[bc]/){ |s| hash[s] } #=> a" # Hash を直接渡した場合のみキーが Symbol でも許容する p "abcabc".gsub(/[bc]/, hash) #=> "aBCaBC" ``` ## 利点 * キーを Symbol で書くことを推奨しているコーディング規約がある * [ruby-style-guide/README.ja.md at japanese · fortissimo1997/ruby-style-guide · GitHub](https://github.com/fortissimo1997/ruby-style-guide/blob/japanese/README.ja.md#symbols-as-keys) * キーを Symbol で定義する方が Hash を書いていて気持ちがいい ## 課題 * `String` と `Symbol` の両方のキーがあった場合どうするか * `"abcabc".sub(/[bc]/, { "b" => "A", b: "C" }) # => ???` * 現状は `String` を優先している * それ以前に `String` と `Symbol` が混ざっている Hash はおかしいのではないだろうか * 警告を出すとか? ## `String#gsub` のユースケースなど ```ruby # http://batsov.com/articles/2013/10/03/using-rubys-gsub-with-a-hash/ def geekify(string) string.gsub(/[leto]/, l: '1', e: '3', t: '7', o: '0') end p geekify('leet') # => '1337' p geekify('noob') # => 'n00b' def doctorize(string) string.gsub(/M(iste)?r/, Mister: 'Doctor', Mr: 'Dr') end p doctorize('Mister Freeze') # => 'Doctor Freeze' p doctorize('Mr Smith') # => 'Dr Smith' ``` ```ruby # https://coderwall.com/p/t4y7cw/ruby-gsub-with-a-hash-or-block amino_acid_hash = { A: 'Ala', R: 'Arg', N: 'Asn' } p "R232A".gsub(/[A-Z]/, amino_acid_hash) # => "Arg232Ala" ``` ```ruby # https://qiita.com/scivola/items/416155c307ec29a37b8f hash = { '&': "&", '<': "<", '>': ">", } p "<Q&A>".gsub(/[&<>]/, hash) # => "<Q&A>" ``` ```ruby # https://qiita.com/pocari/items/34855a9b07ea5006fe80 hash = { '#to#': "taro", '#from#': "jiro", } template = <<EOS hello, #to#. message from #from#. EOS puts template.gsub(/#.*#/, hash) # => hello, taro. # message from jiro. ``` その他、具体的なユースケースを思いついた方がいればコメントいただけると助かります。 ---Files-------------------------------- string_sub_with_symbol_key.patch (2.71 KB) -- https://bugs.ruby-lang.org/