Использование gsub и regex для замены любого другого вхождения символа - PullRequest
0 голосов
/ 11 февраля 2019

Я занимаюсь дизайном карточной игры (пики).Я хочу сохранить каждую руку как хеш.

Это случайно сгенерированная строка, представляющая сингл с 13 картами, где 10c - это ключ, а 10 - это значение

"10c 10 bj 18 2s 15 3s 3 8d 8 as 14 kh 13 8c 8 3c 3 6d 6 kc 13 5d 5 ad 14"

Я хочу заменить пробел ' ' между 10c и 10 на =>, а следующий пробел между 10 и bj запятой ... Этот shoulodвыглядят как 10c=>10,bj=>18 и т. д.

Оттуда я преобразую это в хеш, вызвав Hash # inspect;Тем не менее, я не смог найти способ заменить n-й символ строки, используя gsub.

Я пытался вызвать hand.gsub(' ', '=>'), но это, очевидно, заменяет каждый экземпляр пробела на =>

Ответы [ 2 ]

0 голосов
/ 12 февраля 2019

Я не верю, что использование регулярного выражения - лучший способ создать хеш.Вместо этого я предлагаю использовать методы String # split , Hash :: [] , Hash # transform_values ​​ и String # to_i .Если s - строка, указанная в примере,

Hash[*s.split].transform_values(&:to_i)
  #=> {"10c"=>10, "bj"=>18, "2s"=>15, "3s"=>3, "8d"=>8,
  #    "as" =>14, "kh"=>13, "8c"=> 8, "3c"=>3, "6d"=>6,
  #    "kc" =>13, "5d"=> 5, "ad"=>14} 

Шаги следующие:

a = s.split
  #=> ["10c", "10", "bj", ... , "14"] 
b = Hash[*a]
  #=> {"10c"=>"10", "bj"=>"18", "2s"=>"15", "3s"=>"3",
  #    "8d" => "8", "as"=>"14", "kh"=>"13", "8c"=>"8",
  #    "3c" => "3", "6d"=> "6", "kc"=>"13", "5d"=>"5",
  #    "ad" =>"14"} 
b.transform_values(&:to_i)
  #=> {"10c"=>10, "bj"=>18, "2s"=>15, "3s"=>3, "8d"=>8,
  #    "as" =>14, "kh"=>13, "8c"=> 8, "3c"=>3, "6d"=>6,
  #    "kc" =>13, "5d"=> 5, "ad"=>14} 

Оператор splat (*), заставляет Hash[*a] быть оцененным как Hash["10c", "10", "bj", ... , "14"].

b.transform_values(&:to_i) здесь эквивалентно b.transform_values { |v| v.to_i }.

0 голосов
/ 11 февраля 2019

Вы можете сразу создать хеш с помощью

s = "10c 10 bj 18 2s 15 3s 3 8d 8 as 14 kh 13 8c 8 3c 3 6d 6 kc 13 5d 5 ad 14"
hash = Hash[s.scan(/(\w+) (\d+)/)].transform_values(&:to_i)

Или, для более старых версий Ruby:

hash = Hash[s.scan(/(\w+) (\d+)/)]
hash = Hash[ hash.map{ |a, b| [ a, b.to_i ] } ]
puts hash
# => {"10c"=>10, "bj"=>18, "2s"=>15, "3s"=>3, "8d"=>8, "as"=>14, "kh"=>13, "8c"=>8, "3c"=>3, "6d"=>6, "kc"=>13, "5d"=>5, "ad"=>14}

См. Демонстрационную версию Ruby

Шаблон (\w+) (\d+) сопоставляет и фиксирует в Группе 1 любое одно или несколько символов слова (с (\w+), буквами, цифрами или подчеркиванием вы можете использовать [[:alnum:]]+ или [^\W_] вместо сопоставления букв или цифр), затем соответствует пробелу, а затем записывает в группу 2 любую одну или несколько цифр ((\d+)).String#scan соответствует всем неперекрывающимся вхождениям и возвращает только захваченные подстроки, которые используются в хеш, который создается динамически.

Обратите внимание, что при запуске b.to_i дополнительные проверки не требуются, поскольку \d+будет соответствовать только подстрокам цифр (и они имеют длину 2 на входе).

...