#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)
. Красиво и чисто. 12. 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]
, son => 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) }