2014-02-16 129 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' } 
相關問題