2013-09-20 3 views
16

Будучи новым для Ruby, у меня возникает вопрос о различии между .reject! и .delete_if при работе с хэшами и массивами. Если вы просто хотите избавиться от определенных объектов, существует ли функциональная разница между этими методами? И разум использовать один над другим?Ruby .reject! vs .delete_if

Спасибо!

EDIT Я прочитал документацию ... Думаю, я должен был быть более ясен в своем первоначальном вопросе. Мне было интересно узнать о различиях в эффективности. Они работают по-разному в том, как они удаляют элементы? (Опять же, игнорируя возвращаемое значение. Я понимаю, что это разница. Спасибо!)

+0

@rid so does 'delete_if' –

+2

Разве вы не пробовали читать документация? Это довольно ясно: ['Hash # reject!'] (Http://www.ruby-doc.org/core-2.0.0/Hash.html#method-i-reject-21) и ['Array #reject! '] (http://www.ruby-doc.org/core-2.0.0/Array.html#method-i-reject-21). – toro2k

ответ

13

The documentation довольно ясно об этом.

Разница в том, что если reject! не изменяет массив, он возвращает nil. delete_if вернет неизменный массив.

+0

@JanDvorak «... но возвращает ноль, если никаких изменений не было». Похоже, документация включает в себя возвращаемое значение для меня. –

+1

К сожалению, неверно. Удаление моего ответа и поддержка вашего. Кроме того, проверено в jRuby 1.7.3 ('[" a "]. Delete_if {false}' возвращает массив, а '[" a "]. Reject! {False}' возвращает 'nil') –

+0

@ExplosionPills Спасибо. Я видел это в документации, но, я думаю, я спрашивал больше об эффективности. Игнорируя возвращаемое значение, мне интересно, эффективнее ли удалять элементы? – loganhasson

22
  • reject - создать новый массив без элементов, которые не соответствуют и возвращают новый массив
  • delete_if - удалить элементы, которые не соответствуют с текущего массива и возвращают массив
  • reject! - удалять элементы, которые не соответствуют текущий массив. Верните массив, если что-то было отклонено, или nil, когда нет.
+0

Благодарим вас за организованный ответ. Делает это намного легче, чем разбор того, что пишут другие люди. –

+0

'reject' всегда возвращает * Array *, в то время как' delete_if' и 'reject!' Возвращает исходный объект (который, например, мог быть * Set *). – go2null

4

tl; dr: delete_if кажется немного быстрее. Однако основным соображением для выбора метода является разница в возвращаемом значении, как указано в других ответах.

Так как вы уточнили, что ваш вопрос относительно эффективности, я сделал несколько тестов:

> 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) 

Таким образом, похоже, что за пределами определенного размера delete_if немного быстрее. time определяется как:

def time(&block) 
    puts Benchmark.measure(&block) 
end 

Числа представляют пользователю процессорного времени, время система CPU, сумма пользователей и система CPU раз, и прошедшее в режиме реального времени, соответственно. Вы можете найти here объяснение их значений. Обратите внимание, что, как и в каждом тестировании, YMMV, и вы должны тестировать свои конкретные рабочие процессы, а не мой надуманный пример удаления чисел, кратных 5.

+0

Забота об эффективности двух подобных встроенных модулей - это красная селедка. И вы ничего не доказывали в этом тесте. –

+0

Почему это «красная сельдь»? OP «больше интересовался различиями в эффективности» – dimid

+0

Это красная селедка, потому что никто не должен выбирать между двумя методами, основанными на долях секунды скорости выполнения. Мне бы очень хотелось увидеть код того, кто сделал это основным определением стиля их кодирования. –