что отличается между каждым и собирать метод в Ruby [дубликат]


этот вопрос уже есть ответ здесь:

из этого кода я не знаю разницы между двумя методами,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 59

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! для изменения исходного массива.