Ruby Script для создания массива массивов - PullRequest
1 голос
/ 15 декабря 2010

Я написал простой сценарий очистки экрана, и в конце сценария я пытаюсь создать массив массивов для подготовки к вставке activerecord. Структура, которую я пытаюсь достичь, выглядит следующим образом:

Массив b содержит серию из 10 элементных массивов

b = [[0,1,2,3,4,5,6,7,8,9],[0,1,2,3,4,5,6,7,8,9],[0,1,2,3,4,5,6,7,8,9]]

В настоящее время, когда я пытаюсь распечатать массив b, массив пуст. Я все еще довольно плохо знаком с ruby ​​и программированием в этом отношении и был бы признателен за любые отзывы о том, как получить значения в массиве b и улучшить общий сценарий. Сценарий следует:

require "rubygems"  
require "celerity"
t = 0
r = 0
c = 0
a = Array.new(10)
b = Array.new

  #initialize Browser
  browser = Celerity::IE.new
  #goto Login Page
  browser.goto('http://www1.drf.com/drfLogin.do?type=membership')
  #input UserId and Password
  browser.text_field(:name, 'p_full_name').value = 'username'
  browser.text_field(:name, 'p_password').value = 'password'
  browser.button(:index, 2).click
  #goto DRF Frontpage
  browser.goto('http://www.drf.com/frontpage')
  #goto DRF Entries
  browser.goto('http://www1.drf.com/static/indexMenus/eindex.html')
  #click the link to access the entries
  browser.link(:text, '09').click

  browser.tables.each do |table|
    t = t + 1
      browser.table(:index, t).rows.each do |row| 
        r = r + 1
          browser.table(:index, t).row(:index, r).cells.each do |cell|
            a << cell.text
          end
          b << a
          a.clear         
      end
      r = 0
  end
  puts b
  browser.close

Ответы [ 3 ]

2 голосов
/ 15 декабря 2010

Это небольшое переписывание вашего основного цикла в более рубиноподобном виде.

b = Array.new
browser.tables.each_with_index do |table, t|
  browser.table(:index, 1 + t).rows.each_with_index do |row, r|
    a = Array.new(10)
    browser.table(:index, 1 + t).row(:index, 1 + r).cells.each do |cell|
      a << cell.text
    end
    b << a
  end
end
puts b

Я переместил инициализации массива сразу выше, где они будут необходимы. Конечно, это выбор программиста.

Вместо того, чтобы создавать две переменные счетчика выше, я переключился на использование each_with_index, которое добавляет индексную переменную, начиная с 0. Чтобы получить 1 смещение, я добавляю 1.

Это не большие изменения, но они составляют более сплоченное приложение.

Возвращаясь к исходному коду: я вижу одну проблему, связанную с тем, что вы создаете массив a вне циклов, а затем повторно используете его при назначении b. Это означает, что каждый раз используется один и тот же массив, но очищается и значения сохраняются в нем. Это приведет к тому, что предыдущие значения массива будут перезаписаны, но в результате будут скопированы массивы в b.

require 'pp'

a = []
b = []

puts a.object_id

a[0] = 1
b << a
a.clear

a[0] = 2
b << a

puts 
pp b
b.each { |ary| puts ary.object_id }
# >> 2151839900
# >> 
# >> [[2], [2]]
# >> 2151839900
# >> 2151839900

Обратите внимание, что массив a многократно используется повторно.

Если я изменю a на второй массив, то для b будет два значения, а a - два отдельных объекта:

require 'pp'

a = []
b = []

puts a.object_id

a[0] = 1
b << a
a = []

a[0] = 2
b << a

puts 
pp b
b.each { |ary| puts ary.object_id }
# >> 2151839920
# >> 
# >> [[1], [2]]
# >> 2151839920
# >> 2151839780

Надеюсь, это поможет вам избежать проблемы в будущем.

2 голосов
/ 15 декабря 2010

Ваша проблема в конце:

b << a # push a *reference to* a onto b
a.clear # clear a; the reference in b now points to an empty array!

Если вы удалите ссылку на a.clear и начнете этот цикл с:

browser.tables.each do |table|
  t = t + 1
  a = []

... ты будешь золотым (по крайней мере, в том, что касается построения массива)

1 голос
/ 15 декабря 2010

По вашему вопросу я не могу сказать, есть ли у вас несколько таблиц или нет. Может только один? В каком случае:

b = browser.tables.first.rows.map {|row| row.cells.map(&:text)}

Если у вас есть несколько таблиц и вы действительно хотите массив (таблицы) массивов (строк) массивов (ячеек), это будет

b = browser.tables.map {|t| t.rows.map {|row| row.cells.map(&:text)}}

И если все таблицы имеют одинаковую структуру и вы просто хотите, чтобы все строки были такими, как если бы они были в одной большой таблице, вы можете сделать:

b = browser.tables.map {|t| t.rows.map {|row| row.cells.map(&:text)}}.flatten(1)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...