что отличается между каждым и собирать метод в 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 KA-это массив, но на самом деле это массив нулей [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!для изменения исходного массива.