/ / Повернути непарні елементи з / без блоку - ruby, block, yield

Повернути непарні елементи з / без блоку - рубін, блок, урожай

Я намагаюся повернути непарні елементи, використовуючи цей метод

def odd_elements(array)
retArr = Array.new
array.each_with_index do |item, index|
if block_given?
yield(item)
else
retArr << item
end if index % 2 != 0
end

return retArr
end

щоб я міг пройти обидва ці тести

it "should yield odd elements" do
res = odd_elements([1,2,3,4,5,6])
res.should be_an_instance_of Array
res.should have(3).items
res.should include(2)
res.should include(4)
res.should include(6)
end

it "should yield" do
res = odd_elements([1,2,3,4,5,6]) {|x| x**2 }
res.should be_an_instance_of Array
res.should have(3).items
res[0].should == 4
res[1].should == 16
res[2].should == 36
end

але в другому я зазнаю невдачі. Здається, я не розумію, як поступитися, і мені не вдалося це зробити за дві години, пробуючи стільки різних речей. Не могли б ви пояснити мені, чому це не працює?

Відповіді:

1 для відповіді № 1

yield повертає значення, яке, здається, ви хочете додати retArr:

def odd_elements(array)
retArr = []
array.each_with_index do |item, index|
retArr << (block_given? ? yield(item) : item) if index % 2 != 0
end
retArr
end

Я б особисто віддав перевагу Enumerator (якщо ви використовуєте Ruby 1.9.3+), трохи повільніше, але, можливо, більш читабельно та гнучко:

def odd_elements(array)
Enumerator.new do |e|
odd = false
array.each do |x|
e << x if odd
odd = ! odd
end
end
end

a = [1,2,3,4]

odd_elements(a).to_a #=> [2, 4]
odd_elements(a).map { |x| x * 2 } #=> [4, 8]

1 для відповіді № 2
odd_elements([1,2,3,4,5,6]){|x|p x**2 } #note the p
#=> 4
#=> 16
#=> 36

Це дає прекрасний результат, але ви ніколи не зберігаєте результат у масиві.

odd_elements([1,2,3,4,5,6]).map {|x| x**2 }

збереже результат у масиві.