Rubi.rejeitar! vs. apagar se

Sendo nova na Ruby, tenho uma pergunta sobre a diferença entre o ... rejeitar! e .métodos delete_if ao lidar com traços e arrays. Se apenas querendo se livrar de certos objetos, existe funcionalmente alguma diferença entre os métodos? E uma razão para usar uma em vez da outra?

Obrigado!

editar Li A documentação...Acho que devia ter sido mais claro na minha pergunta original. Queria saber mais sobre as diferenças de eficiência. Será que eles operar de forma diferente em como eles apagam itens? (Novamente, ignorando o valor de retorno. Compreendo que isso seja diferente. Obrigado!)

Author: loganhasson, 2013-09-20

3 answers

A documentação é bastante clara sobre isto.

A diferença é que se reject! não alterar a lista, devolve nil. {[2] } irá devolver a matriz inalterada.

 15
Author: Explosion Pills, 2017-05-15 16:49:55
  • reject - crie um novo array sem elementos que correspondam e devolva o novo array
  • delete_if - apagar os elementos que correspondem à actual e devolver a lista
  • reject! - apagar os elementos que correspondem à lista actual . Retorne a matriz se algo foi rejeitado, ou nil quando nenhum.
 27
Author: Nowaker, 2018-06-15 18:32:03

Tl;dr: delete_if parece um pouco mais rápido. No entanto, a principal consideração para escolher um método é a diferença no valor de retorno, como indicado nas outras respostas.

Uma vez que esclareceu que a sua pergunta é sobre eficiência, fiz alguns testes:
> time { (1..100000).to_a.reject!{ |n| n % 5 == 0 } }
  0.390000   0.000000   0.390000 (  0.394596)
> time { (1..100000).to_a.delete_if{ |n| n % 5 == 0 } }
  0.400000   0.000000   0.400000 (  0.399122)

> time { (1..200000).to_a.reject!{ |n| n % 5 == 0 } }
  1.650000   0.000000   1.650000 (  1.657927)
> time { (1..200000).to_a.delete_if{ |n| n % 5 == 0 } }
  1.630000   0.010000   1.640000 (  1.637719)

> time { (1..300000).to_a.reject!{ |n| n % 5 == 0 } }
  3.700000   0.000000   3.700000 (  3.717206)
> time { (1..300000).to_a.delete_if{ |n| n % 5 == 0 } }
  3.660000   0.000000   3.660000 (  3.686213)

> time { (1..400000).to_a.reject!{ |n| n % 5 == 0 } }
  7.320000   0.020000   7.340000 (  7.361767)
> time { (1..400000).to_a.delete_if{ |n| n % 5 == 0 } }
  7.190000   0.020000   7.210000 (  7.239549)
Então, parece que além de um certo tamanho é um pouco mais rápido. time é definido como:
def time(&block)
  puts Benchmark.measure(&block)
end

Os números representam o tempo de CPU do utilizador, o tempo de CPU do sistema, a soma dos tempos de CPU do utilizador e do sistema, e o tempo real decorrido, respectivamente. Você pode encontrar aqui uma explicação dos seus significados. Note que como em cada benchmark, YMMV, e você deve testar em seus fluxos de trabalho específicos em vez de meu exemplo de remoção de números que são múltiplos de 5.

 3
Author: dimid, 2017-05-23 10:31:09