чем отличается каждый метод и метод collect в Ruby [duplicate]
этот вопрос уже есть ответ здесь:
- массив#каждый против массива#map 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-это массив, но на самом деле это массив нулей [Нил, Нил, Нил], потому что 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
- Это когда вы хотите перебирать массив и делать все, что хотите, на каждой итерации. В большинстве (императивных) языков это молоток "один размер подходит всем", который программисты достигают, когда вам нужно обработать список.
для более функциональных языков вы делаете только такую общую итерацию, если не можете сделать это каким-либо другим способом. Большую часть времени, либо карта или уменьшить будет более подходящим (собирать и вводить в 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]
(значение puts x.succ) пока b == ["L", "Z", "J"]
(исходный массив)
из ruby-doc collect делает следующее:
вызывается один раз для каждого элемента личность. Создает новый массив, содержащий значения, возвращаемые блоком.
каждый всегда возвращает исходный массив. Смысл?
каждый метод определяется всеми классами, которые включают перечисляемый модуль. Object.each
возвращает
Я думаю, что более простой способ понять это было бы, как показано ниже:
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!
для изменения исходного массива.