Умножить четноиндексированные элементы массива на 2, а нечетноиндексированные элементы массива на 3?

#ruby #arrays

#рубиновый #массивы

Вопрос:

У меня есть следующий массив, который содержит все числа от 1 до 10:

 numbers = [1,2,3,4,5,6,7,8,9,10]
 

Я хочу умножить каждый четноиндексированный элемент на 2 и каждый нечетно индексированный элемент на 3. Я хочу, чтобы мой массив выглядел так:

 [2,6,6,12,10,18,14,24,18,30]
 

Я попробовал следующее решение:

 numbers.select do |x|
  if x.even?
    x * 2
  else
    x * 3
  end
  puts x
end
 

К сожалению, это не сработало. У кого-нибудь есть какие-нибудь лучшие методы?

Комментарии:

1. В будущем я предлагаю вам немного подождать, прежде чем выбирать предпочтительный ответ. Поспешное суждение препятствует другим, возможно, лучшим ответам и, на мой взгляд, является невежливым по отношению к тем, кто все еще готовит ответы, когда появляется зеленая галочка. @Cerael не имел права заставлять вас выбирать его или ее ответ всего через семь минут после того, как вы опубликовали вопрос. В случае, если вы не знаете, вы всегда можете изменить свой выбор предпочтительного ответа.

2. Ваше решение довольно близко. Во-первых, удалите puts x , поскольку x это не было изменено x * 2 или x * 3 . Чтобы распечатать результаты, измените select их на each и напишите puts (if x.even?...end) . Чтобы сохранить результаты, измените select на map . Ваша постановка вопроса однозначна, хотя вам не следовало делать numbers последовательность, поскольку это, очевидно, вызвало некоторую путаницу. Что-то вроде numbers = [6, 5, 8, 2] было бы лучше.

Ответ №1:

Похоже, вы хотите, чтобы каждый четный индекс умножался на 2, а нечетные индексы на 3.

Это должно сработать

 numbers = [1,2,3,4,5,6,7,8,9,10]
numbers.map!.with_index { |n, i| i.even? ? n * 2 : n * 3 }
p numbers
# => [2,6,6,12,10,18,14,24,18,30]
 

Что касается вашей попытки, #select выбирает элементы из перечислителя везде, где результат блока является истинным. Если вы хотите изменить счетчик на месте, вы должны использовать #map! . #with_index Метод доступен для всех счетчиков, чтобы включить индекс в ваш блок.

Комментарии:

1. Отлично, отлично! Большое спасибо

2. Если запрашивающий не выбрал ответ в течение нескольких часов или, возможно, дня с момента запроса, разумно опубликовать вежливое напоминание о том, что запрашивающий должен выбрать наиболее полезный ответ, если он был хотя бы один. Просить, чтобы ваш ответ был выбран, и задавать всего несколько минут после публикации вопроса, — это не то, о чем SO. Многие из нас никогда бы не вознаградили такое непрофессиональное поведение повышением голосов.

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

4. Ваше первое предложение несовместимо с тем, что вы делаете, если только вы не ожидаете numbers , что это будет последовательность, и в этом случае вам не нужно with_index .

Ответ №2:

 numbers.map.with_index { |n, i| n * (i.even? ? 2 : 3) }
=> [2, 6, 6, 12, 10, 18, 14, 24, 18, 30]
 

Комментарии:

1. n * (i.even? ? 2 : 3) . Красиво и чисто. 1

2. 1 за хорошее и простое решение заданного вопроса.

Ответ №3:

Ваш блок возвращает не x*2 или x* 3, а результат puts x . Вам нужно удалить эту строку для вашего блока.

Комментарии:

1. Технически, это единственный ответ, который решал проблему OPs.

2. Простое удаление puts x , без изменения select на map , возвращает numbers .

3. Я запутался между collect и select

Ответ №4:

Array#select фильтрует массив на основе оценки кода в блоке. Если блок возвращает «истинное» значение (все, что не false является or nil ), элемент сохраняется, в противном случае он отбрасывается.

То, что вам нужно, — это map метод. map возвращает новый массив, который заполняется возвращением блока.

 [1,2,3,4,5,6,7,8,9,10].map { |x| x.even? ? x * 2 : x * 3 }
 

Комментарии:

1. извините, я имел в виду четные и нечетные индексированные элементы.

Ответ №5:

Немного поиграть в гольф:

 numbers = [1,2,3,4,5,6,7,8,9,10]
puts numbers.each_with_index.map{|n, i| n * (2   i % 2) }
 

Комментарии:

1. Хотя этот блок кода может ответить на вопрос, было бы лучше, если бы вы могли дать небольшое объяснение, почему он это делает.

2. Идан, это экономит вам 45 символов: n=[*1..10];p n.map.with_index{|n,i|n*(2 i%2)}

3. @PlasmaHH, я не уверен, что сложность этого ответа требует объяснения, но вот одно из них: enum = numbers.each_with_index.map => #<Enumerator: #<Enumerator:...:map> . Чтобы увидеть, что перечислитель enum передаст в свой блок: enum.to_a => [[1, 0], [2, 1], [3, 2],...[10, 9]] , первым является n, i = [1, 0] , so n => 1 , i => 0 , и т.д.

4. @PlasmaHH Это не так сложно. each_with_index.map вполне стандартно. Вместо того чтобы проверять четность и использовать условное ( if или ? : ), чтобы решить, как умножать, я использую 2 i % 2 . i % 2 даст результат 0 для четных индексов и 1 для нечетных индексов, а путем сложения 2 мы получим 2 для четных индексов и 3 для нечетных индексов.

Ответ №6:

Вот метод, использующий cycle :

 multiply_by = [2, 3].cycle
numbers.map { |n| n * multiply_by.next }
# => [2, 6, 6, 12, 10, 18, 14, 24, 18, 30]
 

Комментарии:

1. Возможно, вы захотите проверить свою работу: undefined method next’ for nil:NilClass (NoMethodError)`, потому p что не определено.

2. @theTinMan — переименовал переменную, чтобы она была более читаемой … забыл заменить все… : -P исправил это, спасибо

3. Я использую практику копирования кода ответа непосредственно из моего редактора (Sublime) или IRB, поэтому это мой фактический рабочий код, чтобы избежать подобной ситуации.

Ответ №7:

Вот решение в JavaScript.

функция modifyArray(nums) { возвращает nums.map(num => num % 2 == 0 ? num * 2 : num * 3) }