Подтвердить что ты не робот

Что разные между каждым и методом сбора в 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
4b9b3361

Ответ 1

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, nil], потому что puts x.succ возвращает nil (даже если он печатает M AA K).

И

 b = ["L","Z","J"].each{|x| puts x.succ} #=> M AA K

также является массивом. Но его значение равно [ "L", "Z", "J" ], поскольку оно возвращает self.

Ответ 2

Array#each просто берет каждый элемент и помещает его в блок, а затем возвращает исходный массив. Array#collect берет каждый элемент и помещает его в новый массив, который возвращается:

[1, 2, 3].each { |x| x + 1 }    #=> [1, 2, 3]
[1, 2, 3].collect { |x| x + 1 } #=> [2, 3, 4]

Ответ 3

each - это то, когда вы хотите перебирать массив и делать все, что хотите на каждой итерации. На большинстве (императивных) языках это "один размер подходит всем" молоткам, к которым стремятся программисты, когда вам нужно обработать список.

Для более функциональных языков вы делаете только такую ​​родовую итерацию, если не можете сделать это иначе. В большинстве случаев, карта или сокращение будут более подходящими (собирать и вводить в рубине).

collect - это когда вы хотите превратить один массив в другой массив

inject - это когда вы хотите превратить массив в одно значение

Ответ 4

Вот два фрагмента исходного кода, в соответствии с 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 создает новый массив и подталкивает к нему результаты блока; то он возвращает этот новый массив.

Исходные фрагменты: каждый, собирать

Ответ 5

Разница в том, что она возвращает. В приведенном выше примере a == [nil,nil,nil] (значение puts x.succ), а b == ["L", "Z", "J"] (исходный массив)

Из ruby-doc собирает следующее:

Вызывает блок один раз для каждого элемента самостоятельно. Создает новый массив, содержащий значения, возвращаемые блоком.

Каждый всегда возвращает исходный массив. Имеет смысл?

Ответ 6

Каждый из них - это метод, определяемый всеми классами, которые включают в себя модуль Enumerable. Object.each возвращает объект Enumerable::Enumerator. Это то, что другие методы Enumerable используют для итерации через объект. each методы каждого класса ведут себя по-разному.

В классе Array, когда блок передается в each, он выполняет инструкции блока для каждого элемента, но в конце возвращает self.This полезен, когда вам не нужен массив, но вы, возможно, просто хотите для выбора элементов из массива и использования аргументов в качестве других методов. inspect и map возвращает новый массив с возвращаемыми значениями выполнения блока для каждого элемента. Вы можете использовать map! и collect! для выполнения операций с исходным массивом.

Ответ 7

Я думаю, что более простой способ понять это будет следующим:

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