что отличается между каждым и собирать метод в Ruby [дубликат]
этот вопрос уже есть ответ здесь:
- массив#друг против массив#карту 6 ответов
из этого кода я не знаю разницы между двумя методами,collect
и each
.
a = ["L","Z","J"].collect{|x| puts x.succ} #=> M AA K
print a.class #=> Array
b = ["L","Z","J"].each{|x| puts x.succ} #=> M AA K
print b.class #=> Array
7 ответов:
Array#each
принимает массив и применяет данный блок по всем элементам. Он не влияет на массив или создает новый объект. Это просто способ зацикливания элементов. Также он возвращает себя.arr=[1,2,3,4] arr.each {|x| puts x*2}
печатает 2,4,6,8 и возвращает [1,2,3,4] несмотря ни на что
Array#collect
такой же, какArray#map
и он применяет данный блок кода на всех элементах и возвращает новый массив. проще говоря 'проецирует каждый элемент последовательности в новый форма'arr.collect {|x| x*2}
возвращает [2,4,6,8]
и в коде
a = ["L","Z","J"].collect{|x| puts x.succ} #=> M AA K
A-это массив, но на самом деле это массив нулей [nil, nil, nil], потому что
puts x.succ
возвращаетnil
(даже если он печатает M AA K).и
b = ["L","Z","J"].each{|x| puts x.succ} #=> M AA K
также является массивом. Но его значение ["L","Z", "J"], потому что он возвращает себя.
Array#each
просто берет каждый элемент и помещает его в блок, затем возвращает исходный массив.Array#collect
берет каждый элемент и помещает его в новый массив, который возвращается:[1, 2, 3].each { |x| x + 1 } #=> [1, 2, 3] [1, 2, 3].collect { |x| x + 1 } #=> [2, 3, 4]
each
- когда вы хотите перебрать массив, и делать все, что вы хотите в каждой итерации. В большинстве (императивных) языков это молоток "один размер подходит всем", который программисты достигают, когда вам нужно обработать список.для более функциональных языков вы делаете только такую универсальную итерацию, если вы не можете сделать это каким-либо другим способом. В большинстве случаев, либо map, либо reduce будет более подходящим (собирать и вводить в ruby)
collect
- когда вы хотите превратить один массив в другой массив
inject
это когда вы хотите превратить массив в одно значение
вот два фрагмента исходного кода, согласно docs...
VALUE rb_ary_each(VALUE ary) { long i; RETURN_ENUMERATOR(ary, 0, 0); for (i=0; i<RARRAY_LEN(ary); i++) { rb_yield(RARRAY_PTR(ary)[i]); } return ary; } # .... .... .... .... .... .... .... .... .... .... .... .... static VALUE rb_ary_collect(VALUE ary) { long i; VALUE collect; RETURN_ENUMERATOR(ary, 0, 0); collect = rb_ary_new2(RARRAY_LEN(ary)); for (i = 0; i < RARRAY_LEN(ary); i++) { rb_ary_push(collect, rb_yield(RARRAY_PTR(ary)[i])); } return collect; }
rb_yield()
возвращает значение, возвращаемое блоком (см. также это сообщение в блоге о метапрограммировании).так
each
просто доходность и возвращает исходный массив, в то время какcollect
создает новый массив и помещает в него результаты блока; затем он возвращает этот новый массив.
разница в том, что он возвращает. В вашем примере выше
a == [nil,nil,nil]
(значением кладет х.зисс), аb == ["L", "Z", "J"]
(исходный массив)из ruby-doc, collect делает следующее:
вызывается один раз для каждого элемента личность. Создает новый массив, содержащий значения, возвращаемые блоком.
каждый всегда возвращает исходный массив. Имеет смысл?
каждый метод определяется всеми классами, которые включают перечисляемый модуль.
Object.each
возвращает a
Я думаю, что легче разобраться это будет, как показано ниже:
nums = [1, 1, 2, 3, 5] square = nums.each { |num| num ** 2 } # => [1, 1, 2, 3, 5]
вместо этого, если вы используете collect:
square = nums.collect { |num| num ** 2 } # => [1, 1, 4, 9, 25]
и плюс, вы можете использовать
.collect!
для изменения исходного массива.