使用 gsub 和 regex 替换每一个其他出现的字符
Using gsub and regex to replace every other occurrence of a character
我正在设计纸牌游戏(黑桃)。我想将每手牌存储为哈希值。
这是一个随机生成的字符串,表示一张有 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
之间的 space ' '
替换为 =>
和以下 space 之间的 [=] 11=] 和 bj
用逗号...这应该看起来像 10c=>10,bj=>18
等
从那里我将通过调用 Hash#inspect 将其转换为散列;但是,我一直无法找到使用 gsub 替换字符串的第 n 个字符的方法。
我试过调用 hand.gsub(' ', '=>')
但这显然用 =>
替换了 space 的每个实例
您可以立即使用
构建哈希
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}
(\w+) (\d+)
模式匹配并捕获任何一个或多个单词字符(带有 (\w+)
、字母、数字或下划线,您可以使用 [[:alnum:]]+
或 [^\W_]
,而不是匹配字母或数字),然后匹配 space,然后将任何一个或多个数字((\d+)
)捕获到第 2 组。 String#scan
匹配所有非重叠事件,并且仅 returns 捕获的子字符串被利用到动态构建的哈希中。
请注意,当您 运行 b.to_i
时,您不需要额外的检查,因为 \d+
将仅匹配数字子串(并且它们在输入中的长度为 2)。
我不认为使用正则表达式是创建散列的最佳方式。相反,我建议使用方法 String#split, Hash::[], Hash#transform_values and 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 }
.
我正在设计纸牌游戏(黑桃)。我想将每手牌存储为哈希值。
这是一个随机生成的字符串,表示一张有 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
之间的 space ' '
替换为 =>
和以下 space 之间的 [=] 11=] 和 bj
用逗号...这应该看起来像 10c=>10,bj=>18
等
从那里我将通过调用 Hash#inspect 将其转换为散列;但是,我一直无法找到使用 gsub 替换字符串的第 n 个字符的方法。
我试过调用 hand.gsub(' ', '=>')
但这显然用 =>
您可以立即使用
构建哈希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}
(\w+) (\d+)
模式匹配并捕获任何一个或多个单词字符(带有 (\w+)
、字母、数字或下划线,您可以使用 [[:alnum:]]+
或 [^\W_]
,而不是匹配字母或数字),然后匹配 space,然后将任何一个或多个数字((\d+)
)捕获到第 2 组。 String#scan
匹配所有非重叠事件,并且仅 returns 捕获的子字符串被利用到动态构建的哈希中。
请注意,当您 运行 b.to_i
时,您不需要额外的检查,因为 \d+
将仅匹配数字子串(并且它们在输入中的长度为 2)。
我不认为使用正则表达式是创建散列的最佳方式。相反,我建议使用方法 String#split, Hash::[], Hash#transform_values and 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 }
.