2016-11-07 6 views
0

Я пытаюсь поместить массив целых чисел (в конечном счете, чтобы преобразовать их символы ASCII) в массив, созданный звездами, но он просто не работает, и я не знаю почему.Как вставить 2D-массив в другой 2D-массив? (Ruby)

Мой код ниже, и данные представляют собой массив, содержащий 40 столбцов и 22 строки.

image = Array.new(24) { Array.new(42, ' ')} 
(0..23).each do |r| 
    if r == 0 || r == 23 then 
    (0..41).each do |c| 
     image[r][c] = '*' 
    end 
    else 
    (0..41).each do |c| 
     if c == 0 || c == 41 then 
     image[r][c] = '*' 
     else 
     image[r][c] = data[r][c] 
     end 
    end 
    end  
end 


print image 
+0

При попытке запустить код я получаю '' неопределенная локальная переменная или метод 'data'''. Исправьте его, а также укажите текущий (неправильный) вывод и ожидаемый (правильный) результат. – Stefan

+0

Если я добавляю 'data = Array.new (24) {Array.new (42, '-')}', то он работает, хотя вывод действительно сырой. – tadman

ответ

0

Вы делаете это слишком сложно. Разбейте его на шаги. Удалите вложенные циклы и условные обозначения.

1) Захватите строки 0 и 23 из изображения и установите все на «*».

2) Проведите через каждую строку (т.е. image.each do |row| ...) и установите для столбцов 0 и 41 значение «*».

3) Повторитесь через каждую строку и установите другие столбцы в соответствии с данными, находящимися в данных (возможно, здесь необходим вложенный цикл, но не условный).

Edit: полный код может выглядеть примерно так:

#step0 -- create nested array with first and last rows missing. Doesn't need useless spaces. Nil instead. 
image = Array.new(22) { Array.new(42) } 

#step1 --- iterate through the rows and set first and last columns to "*" 
image.each do |row| 
    row[0] = "*" 
    row[41] = "*" 
end 

#step2 -- add first and last rows, which are all "*" 
image.shift(Array.new(42, "*")) 
image.push(Array.new(42, "*")) 

#step3 -- nested loop that matches image to data only if not already set. 
image.each_with_index do |row, ridx| 
    row.each_with_index do |col, cidx| 
    image[row][col] = data[row][col] unless image[row][col] 
    end 
end 

Это действительно может быть просто проще клонировать данные, а затем добавить эту границу к нему. То есть, в конце концов, все, что вы здесь делаете, и может быть источником проблемы, с которой вы сталкиваетесь.

+0

Я действительно не понимаю шаги 2 и 3? пожалуйста, не могли бы вы объяснить дальше? – twigface

+0

это то, что я делаю для шага 2: 'image.each do | row | изображение [ряд] [0] = "*" изображение [ряд] [23] = "*" конец' – twigface

0

Если я правильно понял ваш случай право и у вас есть следующие значения:

image = Array.new(5) { Array.new(10, ' ')} 
data = [[0, 1, 2, 3, 4, 5, 6, 7], [8, 9, 10, 11, 12, 13, 14, 15], [16, 17, 18, 19, 20, 21, 22, 23]] 

Тогда минимальные изменения вашего кода должен выглядеть так:

(0..4).each do |r| 
    (0..9).each do |c| 
    if r == 0 || r == 4 || c == 0 || c == 9 
     image[r][c] = '*' 
    else 
     image[r][c] = data[r.pred][c.pred] 
    end 
    end 
end 

Тогда результат будет выглядеть так:

> image 
#=> [["*", "*", "*", "*", "*", "*", "*", "*", "*", "*"], ["*", 0, 1, 2, 3, 4, 5, 6, 7, "*"], ["*", 8, 9, 10, 11, 12, 13, 14, 15, "*"], ["*", 16, 17, 18, 19, 20, 21, 22, 23, "*"], ["*", "*", "*", "*", "*", "*", "*", "*", "*", "*"]] 
+0

нет это не мои данные. Почему мой код не работает? – twigface

+0

@twigface вы не добавляете значение 'data' –

0

Давайте сначала построим data. Для простоты я предполагаю, что data имеет 6 элементов («rows»), и каждый элемент представляет собой массив из элементов 4 (формирование «столбцов», хотя Ruby фактически не имеет понятия массивов, имеющих строки и столбцы).

ROWS = 6 
COLS = 4 

data = (ROWS*COLS).times.to_a.each_slice(4).to_a 
    #=> [[0, 1, 2, 3], [4, 5, 6, 7], [8, 9, 10, 11], [12, 13, 14, 15], 
    # [16, 17, 18, 19], [20, 21, 22, 23]] 

Теперь нам нужно лишь немного изменить код, чтобы получить желаемый результат.

rows = data.size+2 
    #=> 8 
cols = data.first+2  
    #=> 6 
image = Array.new(rows) { Array.new(cols, ' ')} 
(0...rows).each do |r| # note 3 dots here and below 
    if r == 0 || r == rows-1 
    (0...cols).each do |c| 
     image[r][c] = '*' 
    end 
    else 
    (0...cols).each do |c| 
     if c == 0 || c == cols-1 
     image[r][c] = '*' 
     else 
     image[r][c] = data[r-1][c-1] 
     end 
    end 
    end  
end 

image.each { |row| p row } 

печатает

["*", "*", "*", "*", "*", "*"] 
["*", 0, 1, 2, 3, "*"] 
["*", 4, 5, 6, 7, "*"] 
["*", 8, 9, 10, 11, "*"] 
["*", 12, 13, 14, 15, "*"] 
["*", 16, 17, 18, 19, "*"] 
["*", 20, 21, 22, 23, "*"] 
["*", "*", "*", "*", "*", "*"] 

Более рубин, как способ сделать это состоит в следующем.

image = [['*']*(data.first.size+1)] 
ROWS.times { |i| image << ['*', *data[i], '*'] } 
image << image.first 

image.each { |row| p row } 

Если вы хотите создать красиво отформатированную таблицу, вы можете сделать следующее.

def fmt(data, col_space, boundary_char='*') 
    col_width = data.flatten.map { |n| n.to_s.size }.max + col_space 
    nrows, ncols = data.size, data.first.size 
    header = boundary_char * (col_width * ncols + 2 + col_space) 
    right_border = " "*col_space << boundary_char 
    image = [header] 
    data.each { |row| 
    image << "%s%s%s" % 
     [boundary_char, row.map { |n| n.to_s.rjust(col_width) }.join, right_border] } 
    image << header 
    image 
end 

puts fmt(data, 2) 

печатает

******************** 
* 0 1 2 3 * 
* 4 5 6 7 * 
* 8 9 10 11 * 
* 12 13 14 15 * 
* 16 17 18 19 * 
* 20 21 22 23 * 
******************** 

Шаги следующим образом (data, как определено выше).

col_space = 2 
boundary_char='*' 

a = data.flatten 
    #=> [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 
    # 15, 16, 17, 18, 19, 20, 21, 22, 23] 
b = a.map { |n| n.to_s.size } 
    #=> [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2] 
col_width = b.max + col_space 
    #=> 2 + 2 => 4 

nrows, ncols = data.size, data.first.size 
    #=> [6, 4] 
header = boundary_char * (col_width * ncols + 2 + col_space) 
    #=> * * (4*4 + 2 + 2) 
    #=> "********************" 
right_border = " "*col_space << boundary_char 
    #=> " "*2 << "*" =< " " << "*" => " *" 
image = [header] 
    #=> ["********************"] 

data.each { |row| 
    puts "row=#{row}" 
    puts " image row=#{"%s%s%s" % [boundary_char, 
    row.map { |n| n.to_s.rjust(col_width) }.join, right_border]}" 
    image << "%s%s%s" % [boundary_char, 
    row.map { |n| n.to_s.rjust(col_width) }.join, right_border] } 

row=[0, 1, 2, 3] 
    image row=* 0 1 2 3 * 
row=[4, 5, 6, 7] 
    image row=* 4 5 6 7 * 
row=[8, 9, 10, 11] 
    image row=* 8 9 10 11 * 
row=[12, 13, 14, 15] 
    image row=* 12 13 14 15 * 
row=[16, 17, 18, 19] 
    image row=* 16 17 18 19 * 
row=[20, 21, 22, 23] 
    image row=* 20 21 22 23 * 

Затем

image << header 
image 

возвращает результат выше.