Ruby.reject! vs.delete_if

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

Благодарю!

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

Ответ 1

В документации это довольно ясно.

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

Ответ 2

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

Ответ 3

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, сумму времени процессора пользователя и системы и истекшее реальное время соответственно. Вы можете найти здесь объяснение их значений. Обратите внимание, что, как и в каждом тестировании, YMMV, и вы должны тестировать свои конкретные рабочие процессы, а не мой надуманный пример удаления чисел, кратных 5.