描述:
我的代码的目的是接受一系列R和C的输入,并简单地将字符后面的每个数字存储在其正确的数组中。
例如:“输入格式如下:R1C4R2C5
列数组:[4,5]行数组:[1,2]
我的问题是我得到这样的输出:
[" ", 1]
[" ", 4]
[" ", 2]
[" ", 5]
**如何在一个数组中获取R之后的所有Row整数,以及在另一个单独数组中使用C之后的所有Column整数。我不想创建多个数组,而只是两个。
帮助!
CODE:
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
答案 0 :(得分:2)
x = "R1C4R2C5"
col = []
row = []
x.chars.each_slice(2) { |u| u[0] == "R" ? row << u[1] : col << u[1] }
p col
p row
答案 1 :(得分:1)
代码的主要问题是您复制行和列的操作。你想写“干”代码,代表“不要重复自己”。
从您的代码作为模型开始,您可以通过编写这样的方法来干掉它,从输入字符串中提取所需的信息,并为行调用一次,为列调用一次:
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]]
等等。
答案 2 :(得分:1)
rows, cols = "R1C4R2C5".scan(/R(\d+)C(\d+)/).flatten.partition.with_index {|_, index| index.even? }
> rows
=> ["1", "2"]
> cols
=> ["4", "5"]
或者
rows = "R1C4R2C5".scan(/R(\d+)/).flatten
=> ["1", "2"]
cols = "R1C4R2C5".scan(/C(\d+)/).flatten
=> ["4", "5"]
要修复您的代码使用:
word2.each {|a| col.push(a.delete('C')) if a.include? 'C' }
word2.each {|a| row.push(a.delete('R')) if a.include? 'R' }