Почему / Как моя переменная получает значение ноль - PullRequest
1 голос
/ 17 сентября 2011

У меня есть некоторый код, который читает файл в массив строк, а затем анализирует эти строки, чтобы получить структурированные данные. Входной файл имеет различные типы данных, которые необходимо обрабатывать по-разному, кроме того, существуют основные разделы для различных учетных записей (мобильных номеров).

Я перебираю строки в поисках строки счета, идентифицирую учетную запись, а затем хочу использовать эту учетную запись, пока не обнаружу следующую строку счета. Линии между ними потенциально представляют различные типы данных, принадлежащих этой учетной записи. Проблема в том, что после того, как я нахожу строку счета и устанавливаю локальную переменную (cur_num), переменная устанавливается в nil, когда я хочу ее использовать. Почему, как это происходит? Я изучаю Ruby, поэтому я хочу больше, чем просто исправить - я хочу понять, почему это так работает.

Вот мой код:

  count = 0
  cur_num = ""
  lines.each do |line|
  unless (line.strip.eql?(""))  # edited due to comment from normalocity
    if (line.slice(0,15) == "Mobile Number:,")
      cur_num = line.slice(15,12)
      count = 1
      puts "Current Number: #{cur_num}"
      #puts "Object Type: #{cur_num.class}"
    else 
      data = line.strip.split(',')
      if (data.length > 8)
        data.unshift(cur_num)
        #if (count.modulo(10) == 0 || count == 1)
          puts "[#{cur_num}] #{data.inspect}"
          #pp data
        #end
        count += 1
      end
    end
  end
end

Обзор структуры входных данных будет выглядеть следующим образом:

Account 1
    Data Section A
        data line 1
        data line 2
     Data Section B
        data line 1
        data line 2
Account 2
    Data Section A
        data line 1
        data line 2
     Data Section B
        data line 1
        data line 2

end

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

lines = []
lines.push("ATT Wireless Bill")
lines.push("")
lines.push("Mobile Number:,770-555-1212")
lines.push("item,date,time,number called,rate period,plan type,minutes,airtime charge,ld charge,total charge")
lines.push("")
lines.push("1,2011-01-02,6:56AM,404-555-1212,NW,UNW,4,0.00,0.00,0.00")
lines.push("")
lines.push("2,2011-01-03,6:56AM,404-555-1212,NW,UNW,4,0.00,0.00,0.00")
lines.push("")
lines.push("1,2011-01-03,7:56AM,404-555-1213,DT,UM2M,5,0.00,0.00,0.00")
lines.push("")
lines.push("Mobile Number:,770-555-1213")
lines.push("item,date,time,number called,rate period,plan type,minutes,airtime charge,ld charge,total charge")
lines.push("")
lines.push("1,2011-01-02,6:56AM,404-555-1212,NW,UNW,4,0.00,0.00,0.00")
lines.push("")
lines.push("2,2011-01-03,6:56AM,404-555-1212,NW,UNW,4,0.00,0.00,0.00")
lines.push("")
lines.push("1,2011-01-03,7:56AM,404-555-1213,DT,UM2M,5,0.00,0.00,0.00")
lines.push("")

Ответы [ 2 ]

1 голос
/ 18 сентября 2011

Ответ на ответ Почему / Как моя переменная имеет значение nil

Без cur_num = "" вы не инициализируете cur_num вне цикла (lines.each).Таким образом, cur_num инициализируется в каждом цикле.

Я ожидал бы ошибку undefined local variable or method, но кажется, что cur_num создается в каждом цикле, даже если ветвь if не выполняется.Итак, у вас есть cur_num, но без значения (или лучше: это ноль).

Я добавил короткий пример, чтобы показать, что переменная создается, даже если код не выполняется:

if false
  a = 1
else
  p a #works fine, a was created, but it is nil
  p b #undefined local variable or method `b' 
end

Приложение II:

Следующий код показывает, что переменная внутри цикла является «внутренней петлей».2-й (и последующий) цикл (ы) начинаются без переменной a.

#~ a = 0  # uncomment to compare
5.times{
  if defined? a
    puts "a is defined as #{a.inspect}"
  else
    puts "a is not defined"
    a = 1 #define it now
  end
}

Вопросы, связанные с данной: Сфера сбивает с толку


Я изменил вашкод немного.Когда я разбираю тексты, подобные вашему, я предпочитаю использовать case -словие с регулярными выражениями:

count = 0
cur_num = ""
DATA.each_line do |line|
  case line
    when /\A\s\Z*/ #skip empty lines
    when /Mobile Number:,(.{12})/
      cur_num = $1
      count = 1
      puts "Current Number: #{cur_num}"
      #puts "Object Type: #{cur_num.class}"
    else 
      data = line.strip.split(',')
      if data.length > 8
        data.unshift(cur_num)
        #if (count.modulo(10) == 0 || count == 1)
          puts "[#{cur_num}] #{data.inspect}"
          #pp data
        #end
        count += 1
      end #(data.length > 8)
  end #case line
end

__END__
ATT Wireless Bill

Mobile Number:,770-555-1212
item,date,time,number called,rate period,plan type,minutes,airtime charge,ld charge,total charge

1,2011-01-02,6:56AM,404-555-1212,NW,UNW,4,0.00,0.00,0.00

2,2011-01-03,6:56AM,404-555-1212,NW,UNW,4,0.00,0.00,0.00

1,2011-01-03,7:56AM,404-555-1213,DT,UM2M,5,0.00,0.00,0.00

Mobile Number:,770-555-1213
item,date,time,number called,rate period,plan type,minutes,airtime charge,ld charge,total charge

1,2011-01-02,6:56AM,404-555-1212,NW,UNW,4,0.00,0.00,0.00

2,2011-01-03,6:56AM,404-555-1212,NW,UNW,4,0.00,0.00,0.00

1,2011-01-03,7:56AM,404-555-1213,DT,UM2M,5,0.00,0.00,0.00
0 голосов
/ 18 сентября 2011

Посмотрев на это более часа, сравнив две почти идентичные версии, одну, которая работала, другую, которая не работала, я могу заставить ее выйти из строя или преуспеть, закомментировав одну строку.Вот точный код, который я выполняю: [Изменить примечание, изменив код, чтобы предотвратить вертикальную полосу прокрутки в примере кода]

#!/usr/local/bin/ruby
my_input ="ATT Wireless Bill\n\nMobile Number:,770-555-1212\n\nitem,date,time,number called,rate period,plan type,minutes,airtime charge,ld charge,total charge\n\n1,2011-01-02,6:56AM,404-555-1212,NW,UNW,4,0.00,0.00,0.00\n\n"
my_input << "2,2011-01-03,6:56AM,404-555-1212,NW,UNW,4,0.00,0.00,0.00\n\n1,2011-01-03,7:56AM,404-555-1213,DT,UM2M,5,0.00,0.00,0.00\n\nMobile Number:,770-555-1213\n\nitem,date,time,number called,rate period,plan type,minutes,airtime charge,ld charge,total charge\n\n"
my_input << "1,2011-01-02,6:56AM,404-555-1212,NW,UNW,4,0.00,0.00,0.00\n\n2,2011-01-03,6:56AM,404-555-1212,NW,UNW,4,0.00,0.00,0.00\n\n1,2011-01-03,7:56AM,404-555-1213,DT,UM2M,5,0.00,0.00,0.00\n\n"
lines = my_input.split("\n")
count = 0
cur_num = "" # Line  7 - Comment out this line to see failure
lines.each do |line|
unless (line.strip.eql?(""))
  if (line.slice(0,15) == "Mobile Number:,")
    cur_num = line.slice(15,12)
    count = 1
    puts "Current Number: #{cur_num}"
    #puts "Object Type: #{cur_num.class}"
  else 
    data = line.strip.split(',')
    if (data.length > 8)
      data.unshift(cur_num)
      #if (count.modulo(10) == 0 || count == 1)
        puts "[#{cur_num}] #{data.inspect}"
        #pp data
      #end
      count += 1
    end
    end
  end
end

Если я закомментирую строку 7, то cur_val будет нулевым в строках 18 и 20.

Может кто-нибудь объяснить, почему?

...