描述:
我的代码的目的是接受一系列R和C的输入,并简单地将字符后面的每个数字存储在其适当的数组中。
例如:“输入格式如下:R1C4R2C5
列数组:[4,5]行数组:[1,2]
我的问题是我得到这样的输出:
[" ", 1]
[" ", 4]
[" ", 2]
[" ", 5]
**我如何在一个数组中获得所有紧随R的行整数,以及在另一个单独的数组中紧随C的所有列整数。我不想创建多个数组,而只需创建两个。
帮助!
代码:
puts 'Please input: '
input = gets.chomp
word2 = input.scan(/.{1,2}/)
col = []
row = []
word2.each {|a| col.push(a.split(/C/)) if a.include? 'C' }
word2.each {|a| row.push(a.split(/R/)) if a.include? 'R' }
col.each do |num|
puts num.inspect
end
row.each do |num|
puts num.inspect
end
代码的主要问题是复制行和列的操作。您想编写“ DRY”代码,代表“不要重复自己”。
从将代码作为模型开始,您可以通过编写如下方法将其干燥,以从输入字符串中提取所需的信息,然后对行调用一次,对列调用一次:
def doit(s, c)
...
end
这s
是输入字符串,c
是字符串“ R”或“ C”。在该方法中,您要提取以的值开头c
和后跟数字的子字符串。您决定使用String#scan是一个不错的决定,但您需要使用其他正则表达式:
def doit(s, c)
s.scan(/#{c}\d+/)
end
我将解释正则表达式,但让我们首先尝试该方法。假设字符串是:
s = "R1C4R2C5"
然后
rows = doit(s, "R") #=> ["R1", "R2"]
cols = doit(s, "C") #=> ["C4", "C5"]
这不是您想要的,但是很容易解决。首先,正则表达式。正则表达式首先寻找一个字符#{c}
。#{c}
将变量的值转换c
为文字字符,在这种情况下为“ R”或“ C”。\d+
表示字符后#{c}
必须跟一个或多个数字0-9
,与下一个非数字(此处为“ R”或“ C”)或字符串末尾的数字相同。
现在让我们修复该方法:
def doit(s, c)
a = s.scan(/#{c}\d+/)
b = a.map {|str| str[1..-1]}
b.map(&:to_i)
end
rows = doit(s, "R") #=> [1, 2]
cols = doit(s, "C") #=> [4, 5]
成功!与以前一样,a => ["R1", "R2"]
如果c => "R"
和a =>["C4", "C5"]
如果c => "C"
。a.map {|str| str[1..-1]}
将每个元素映射a
到一个字符串,该字符串包含除第一个字符(例如"R12"[1..-1] => "12"
)以外的所有字符,因此我们具有b => ["1", "2"]
或b =>["4", "5"]
。然后,我们再次应用map
将这些字符串转换为它们的Fixnum等效项。该表达式b.map(&:to_i)
是的简写
b.map {|str| str.to_i}
该方法将返回最后计算的数量,因此,如果您想要的是此处所需要的数量,则无需return
在末尾声明。
但是,这可以通过两种方式简化。首先,我们可以通过删除最后一个语句并将上面的一个更改为以下内容来组合最后两个语句:
a.map {|str| str[1..-1].to_i}
这也摆脱了局部变量b
。第二个改进是“链接”剩余的两个语句,这也使我们摆脱了另一个临时变量:
def doit(s, c)
s.scan(/#{c}\d+/).map { |str| str[1..-1].to_i }
end
这是典型的Ruby代码。
请注意,通过这种方式,不需要字符串中的行和列引用交替出现,并且数值可以具有任意数量的数字。
这是做相同事情的另一种方法,有些人可能认为它更像Ruby:
s.scan(/[RC]\d+/).each_with_object([[],[]]) {|n,(r,c)|
(n[0]=='R' ? r : c) << n[1..-1].to_i}
这是正在发生的事情。认为:
s = "R1C4R2C5R32R4C7R18C6C12"
然后
a = s.scan(/[RC]\d+/)
#=> ["R1", "C4", "R2", "C5", "R32", "R4", "C7", "R18", "C6", "C12"]
scan
使用正则表达式/([RC]\d+)/
提取以'R'或'C'开头的子字符串,后跟一个或多个数字,直到字符串的下一个字母或结尾。
b = a.each_with_object([[],[]]) {|n,(r,c)|(n[0]=='R' ? r : c) << n[1..-1].to_i}
#=> [[1, 2, 32, 4, 18], [4, 5, 7, 6, 12]]
行值由[1, 2, 32, 4, 18]
;给出;列值[4, 5, 7, 6, 12]
。
Enumerable#each_with_object(v1.9 +)创建一个由两个空数组组成的数组[[],[]]
。第一个子数组将包含行值,第二个子数组将包含列值。这两个子数组分别由块变量r
和表示c
。
的第一个元素a
是“ R1”。这在块中由变量表示n
。自从
"R1"[0] #=> "R"
"R1"[1..-1] #=> "1"
我们执行
r << "1".to_i #=> [1]
所以现在
[r,c] #=> [[1],[]]
下一个元素a
是“ C4”,因此我们将执行:
c << "4".to_i #=> [4]
所以现在
[r,c] #=> [[1],[4]]
等等。
本文收集自互联网,转载请注明来源。
如有侵权,请联系 [email protected] 删除。
我来说两句