2014-02-16 2 views
-1

ОПИСАНИЕ:Как создать два отдельных массива с одного входа?

Цель моего кода - ввести ввод последовательности R и C и просто сохранить каждое число, которое приходит после символа в его собственном массиве.

Пример: «Формат ввода выглядит следующим образом: R1C4R2C5

Колонка Массив: [4, 5] Строка Массив: [1,2]

Моя проблема я получаю вывода, как это :.

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

** Как я могу получить все целые числа Их следующие R в одном массиве, и все целые числа столбцов следующие с в другом отдельном массиве Я не хочу, чтобы создать несколько массивов, а только два

.

Помощь!

КОД:

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

Основная проблема с вашим кодом является то, что вы повторить операции для строк и столбцов. Вы хотите написать код «СУХОЙ», который означает «не повторяйте себя».

Начиная с кодом в качестве модели, вы можете высушить его, написав метод, как это, чтобы извлечь информацию, которую вы хотите от входной строки, и ссылаться на него один раз для строки и один раз для столбцов:

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].

Enumerable#each_with_object (v1.9 +) создает массив, состоящий из двух пустых массивов, [[],[]]. Первый subarray будет содержать значения строк, второй - значения столбца. Эти два подмассива представлены блочными переменными 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
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' } 
Смежные вопросы