简体   繁体   English

使用gsub和regex替换所有其他出现的字符

[英]Using gsub and regex to replace every other occurrence of a character

I am designing a card game (spades). 我正在设计一个纸牌游戏(黑桃)。 I want to store each hand as a hash. 我想将每手存储为哈希。

This is a randomly generated string representing a single had with 13 cards where 10c is the key and 10 is the value 这是一个随机生成的字符串,表示一个人有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"

I want to replace the space ' ' between 10c and 10 with a => and the following space between 10 and bj with a comma... This shoulod look like 10c=>10,bj=>18 etc. 我想用=>替换10c10之间的空格' ' ,并用逗号替换下面的10bj之间的空格...这个单肩看起来像10c=>10,bj=>18等。

From there I will convert this to a hash by calling Hash#inspect; 从那里,我将通过调用Hash#inspect将其转换为哈希。 however, I haven't been able to find a way to replace the nth character of a string using gsub. 但是,我还没有找到使用gsub替换字符串的第n个字符的方法。

I've tried calling hand.gsub(' ', '=>') but this obviously replaces every instance of a space with => 我已经打过电话hand.gsub(' ', '=>')但是这显然与替代空间的每个实例=>

You may build the hash right away with 您可以立即构建哈希

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)

Or, for older Ruby versions: 或者,对于较旧的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}

See the Ruby demo 观看Ruby演示

The (\\w+) (\\d+) pattern matches and captures into Group 1 any one or more word chars (with (\\w+) , letters, digits or underscores, you may use [[:alnum:]]+ , or [^\\W_] , instead to match letters or digits), then matches a space, and then captures into Group 2 any one or more digits ( (\\d+) ). (\\w+) (\\d+)模式将任何一个或多个单词字符(带有(\\w+) ,字母,数字或下划线的字符(\\w+) (\\d+)匹配并捕获到组1中,您可以使用[[:alnum:]]+[^\\W_] ,而不是匹配字母或数字),然后匹配一个空格,然后将任意一个或多个数字( (\\d+) )捕获到组2中。 String#scan matches all non-overlapping occurrences, and only returns captured substrings that are leveraged into a hash that is built dynamically. String#scan匹配所有不重叠的事件,并且仅返回被利用到动态构建的哈希中的捕获子字符串。

Note that when you run b.to_i , you need no additional checks since \\d+ will only match digit substrings (and they are of length 2 in the input). 请注意,当您运行b.to_i ,您不需要进行其他检查,因为\\d+仅匹配数字子字符串(它们在输入中的长度为2)。

I don't believe the use of a regular expression is the best way to create the hash. 我不认为使用正则表达式是创建哈希的最佳方法。 Instead, I suggest using the methods String#split , Hash::[] , Hash#transform_values and String#to_i . 相反,我建议使用String#splitHash :: []Hash#transform_valuesString#to_i方法 If s is the string given in the example, 如果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} 

The steps are as follows. 步骤如下。

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} 

The splat operator ( * ), causes Hash[*a] to be evaluated as Hash["10c", "10", "bj", ... , "14"] . splat运算符( * )使Hash[*a]评估为Hash["10c", "10", "bj", ... , "14"]

b.transform_values(&:to_i) is here equivalent to b.transform_values { |v| v.to_i } b.transform_values(&:to_i)在这里等效于b.transform_values { |v| v.to_i } b.transform_values { |v| v.to_i } . b.transform_values { |v| v.to_i }

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM