2016-01-24 3 views
0

Я пытаюсь написать код, который примет массив чисел и напечатает строковое представление диапазона чисел.Почему я получаю IndexError

def rng (arr) 
    str = arr[0].to_s 
    idx = 1 
    arr.each do |i| 
    next if arr.index(i) == 0 
    if arr[arr.index(i)-1] == i - 1 
     unless str[idx - 1] == "-" 
     str[idx] = "-" 
     #else next 
     end 
     #puts "if statement str: #{str}, idx: #{idx}" 
    else 
     str[idx] = arr[arr.index(i)-1].to_s 
     idx += 1 
     str[idx] = ","+ i.to_s 
    end 
    idx += 1 
    end 
    puts "str = #{str} and idx = #{idx}" 
end 

rng [0, 1, 2, 3, 8] #"0-3, 8" 

Я получаю эту ошибку:

arrayRange_0.rb:9:in `[]=': index 3 out of string (IndexError) 

Может кто-нибудь объяснить, почему? Когда я раскомментирую else next, он работает. Не знаю, почему.

ответ

1

Когда вы получите эту ошибку, str содержит значение 0-, которая имеет длину всего 2 символов - поэтому он не может быть проиндексирован в положение 3.

Добавить эту строку перед строкой 9, которая вызывает ваш ошибка:

puts "str = #{str}, idx = #{idx}" 

Он будет:

str = 0, idx = 1 
str = 0-, idx = 3 
0

Вот как можно это сделать:

def rng(arr) 
    ranges = [] 
    arr.each do |v| 
    if ranges.last && ranges.last.include?(v-1) 
     # If this is the next consecutive number 
     # store it in the second element 
     ranges.last[1] = v 
    else 
     # Add a new array with current value as the first number 
     ranges << [v] 
    end 
    end 
    # Make a list of strings from the ranges 
    # [[0,3], [8]] becomes ["0-3", "8"] 
    range_strings = ranges.map{|range| range.join('-') } 
    range_strings.join(', ') 
end 


p rng [0, 1, 2, 3, 8] 
# results in "0-3, 8" 

Как и предыдущий ответ говорит, ваш индекс находится за пределами строки

Смежные вопросы