2014-02-16 93 views
-1

描述:如何从一个输入创建两个独立的数组?

我的代码的目的是输入一个R和C序列的输入,并简单地将字符后面的每个数字存储在其正确的数组中。

,例如:“输入格式如下:R1C4R2C5

列阵列:[4,5]排阵:[1,2]

我的问题是我正在输出这样:

[" ", 1] 
[" ", 4] 
[" ", 2] 
[" ", 5] 

**我如何获得以下在另一个单独的列C以下在一个阵列中所有R的行整数,并将所有列整数我不想创建多个磁盘阵列,而只有两个

帮助!

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

是数字的数字? –

回答

1

与您的代码的主要问题是,你复制操作的行和列。你想写“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代码。

请注意,通过这样做,不需要字符串中的行和列引用交替,并且数字值可以具有任意数字的数字。

这里的另一种方式做同样的事情,有些人可能看到的是更红宝石般:

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]。 (v1.9 +)创建一个由两个空数组组成的数组,[[],[]]。第一个子数组将包含行值,第二个列值。这两个子阵列分别由块变量rc表示。

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
x = "R1C4R2C5" 
col = [] 
row = [] 
x.chars.each_slice(2) { |u| u[0] == "R" ? row << u[1] : col << u[1] } 
p col 
p row 
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' } 
相关问题