Умножение элемента массива в цикле while - PullRequest
1 голос
/ 13 апреля 2019

У меня есть массив целых чисел, и я пытаюсь умножить каждый второй элемент на 2, перемещаясь назад в массиве. Однако он, похоже, не принимает оператор * для элемента массива, в результате появляется сообщение об ошибке: неопределенный метод `* 'для nil: NilClass (NoMethodError)

 index = array.length
  while index > 0
    array[index] * 2
    index - 2
  end

Я проверил класс элементов массива, и это действительно целое число, поэтому я не уверен, почему это не работает.

Спасибо.

Ответы [ 4 ]

1 голос
/ 13 апреля 2019

Если вы исправите индексирование, как предлагали другие, и измените третью и четвертую строки, чтобы фактически изменить переменные массива и индекса, тогда ваш код работает, как и предполагалось, для любого массива с четным числом элементов.

index = array.length - 1
while index > 0
  array[index] *= 2
  index -= 2
end

# array now =='s [4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4]

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

array.map.with_index { |n, i| i.odd? ? n * 2 : n }
# Or if you prefer,
array.map.with_index { |n, i| if i.odd? then n * 2 else n end }

#=> [4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4]
1 голос
/ 13 апреля 2019

Вы можете перебрать обратный массив с индексами, а затем отменить результат Array # reverse i % 3 используется для умножения каждого третьего элемента.

Ошибка undefined method *' for nil:NilClass (NoMethodError) в вашем примере появляется потому, что array.length равно 16 (элементы в массиве), но индексы начинаются с 0, поэтому последний индекс равен 15, и на первой итерации вы пытаетесь получить доступ к массиву [16], который не существует, поэтому это nil

array = [4, 2, 4, 2, 4, 2, 4, 2, 4, 2, 4, 2, 4, 2, 4, 2]
result = array.reverse.each_with_index.map do |x, i|
  (i % 3).zero? ? x * 2 : x
end.reverse
# p result
#=> [8, 2, 4, 4, 4, 2, 8, 2, 4, 4, 4, 2, 8, 2, 4, 4]

ОБНОВЛЕНИЕ: Sekalf Nroc ответ хорош с odd?, если вам нужно, чтобы каждый 2-й элемент умножался, но если у вас было, например, 15 элементов, вы могли видеть неожиданные результаты, поэтому reverse все еще нужно было пройти массив назад, комбинируя эти подходы, вы можете сделать что-то вроде этого:

array = [4, 2, 4, 2, 4, 2, 4, 2, 4, 2, 4, 2, 4, 2, 4, 2, 99]
p array.map.with_index { |n, i| i.odd? ? n * 2 : n } # WRONG RESULT
#=>[4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 99]
p array.reverse.map.with_index { |n, i| i.even? ? n * 2 : n }.reverse
#=>[8, 2, 8, 2, 8, 2, 8, 2, 8, 2, 8, 2, 8, 2, 8, 2, 198]
0 голосов
/ 14 апреля 2019

Другой подход, который использует Числовой # шаг .Он хорошо работает со всеми примерами даже с другим шагом (array3)

array1 = [4, 2, 4, 2, 4, 2, 4, 2, 4, 2, 4, 2, 4, 2, 4, 2]
array2 = [2, 4, 2, 4, 2, 4, 2, 4, 2, 4, 2, 4, 2, 4, 2, 4, 2]
array3 = [2, 4, 4, 2, 4, 4, 2, 4, 4, 2, 4, 4, 2, 4, 4, 2]

(array1.size - 1).step(0, -2).each { |i| array1[i] *= 2 }
(array2.size - 1).step(0, -2).each { |i| array2[i] *= 2 }
(array3.size - 1).step(0, -3).each { |i| array3[i] *= 2 }

p array1, array2, array3
#=>[4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4]
#=>[4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4]
#=>[4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4]
0 голосов
/ 14 апреля 2019

Вы можете использовать Range, который обеспечивает метод Range # step . Например, учитывая массив:

ary = [4, 2, 4, 2, 4, 2, 4, 2, 4, 2, 4, 2, 4, 2, 4, 2]

Это способ «умножить каждый второй элемент на 2, перемещаясь назад в массиве», используя Array # reverse_each :

(1...ary.size).step(2).each { |i| ary.size.odd? ? ary[i] *=2 : ary[i-1] *=2 }
#=> [4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4]

Обратите внимание, что первая часть (1...ary.size).step(2).to_a возвращает нечетные индексы:

#=> [1, 3, 5, 7, 9, 11, 13, 15]

Также обратите внимание на три точки ... в диапазоне.

Для ary = [2, 4, 2] #=> [2, 8, 2]

Для ary = [2, 4, 2, 4] #=> [4, 4, 4, 4]

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...