Граф, размер, длина... слишком много вариантов в Ruby?
Я не могу найти окончательного ответа на это, и я хочу убедиться, что я понимаю это на "n-м уровне": -)
a = { "a" => "Hello", "b" => "World" }
a.count # 2
a.size # 2
a.length # 2
a = [ 10, 20 ]
a.count # 2
a.size # 2
a.length # 2
Так что использовать? Если я хочу знать, имеет ли более одного элемента, то это, похоже, не имеет значения, но я хочу убедиться, что я понимаю реальную разницу. Это относится и к массивам. Я получаю те же результаты.
Кроме того, я понимаю, что count/size/length имеют разные значения с помощью ActiveRecord. Меня больше всего интересует чистый Ruby (1.92) прямо сейчас, но если кто-то хочет перекликаться с разницей AR, это тоже будет оценено.
Спасибо!
Ответы
Ответ 1
Для массивов и хешей size
является псевдонимом для length
. Они являются синонимами и делают то же самое.
count
более универсален - он может принимать элемент или предикат и подсчитывать только те элементы, которые соответствуют.
> [1,2,3].count{|x| x > 2 }
=> 1
В случае, когда вы не предоставляете параметр для подсчета, он имеет в основном тот же эффект, что и длина вызова. Однако может быть разница в производительности.
Из исходного кода для Array видно, что они делают почти то же самое. Вот код C для реализации array.length
:
static VALUE
rb_ary_length(VALUE ary)
{
long len = RARRAY_LEN(ary);
return LONG2NUM(len);
}
И вот соответствующая часть из реализации array.count
:
static VALUE
rb_ary_count(int argc, VALUE *argv, VALUE ary)
{
long n = 0;
if (argc == 0) {
VALUE *p, *pend;
if (!rb_block_given_p())
return LONG2NUM(RARRAY_LEN(ary));
// etc..
}
}
Код для array.count
выполняет несколько дополнительных проверок, но в конце вызывает тот же самый код: LONG2NUM(RARRAY_LEN(ary))
.
Хеши (исходный код), с другой стороны, похоже, не реализуют собственную оптимизированную версию count
, поэтому реализация из Enumerable
(исходный код), который выполняет итерацию по всем элементам и подсчитывает их один за другим.
В общем, я бы посоветовал использовать length
(или его псевдоним size
), а не count
, если вы хотите знать, сколько элементов вообще существует.
В отношении ActiveRecord, с другой стороны, существуют важные различия. прочитайте это сообщение:
Ответ 2
Существует важная разница для приложений, которые используют соединения с базой данных.
Когда вы используете много ORM (ActiveRecord, DataMapper и т.д.), общее понимание состоит в том, что .size будет генерировать запрос, который запрашивает все элементы из базы данных ('select * from mytable'), а затем дает вам количество полученных элементов, тогда как .count будет генерировать один запрос ( "select count (*) from mytable" ), который значительно быстрее.
Поскольку эти ОРМ настолько распространены, я следую принципу наименьшего удивления. В общем случае, если у меня уже есть что-то в памяти, то я использую .size, и если мой код будет генерировать запрос к базе данных (или внешнюю службу через API), я использую .count.
Ответ 3
В большинстве случаев (например, Array или String) size
является псевдонимом для length
.
count
обычно исходит из Enumerable и может принимать необязательный предикатный блок. Таким образом, enumerable.count {cond}
является [примерно] (enumerable.select {cond}).length
- он может, конечно, обходить промежуточную структуру, поскольку ему просто нужно количество совпадающих предикатов.
Примечание. Я не уверен, что count
заставляет оценивать перечисление, если блок не указан, или если это возможно, коротко замыкается на length
.
Изменить (и спасибо Mark ответ!): count
без блока (по крайней мере для массивов) не заставляет оценивать. Я полагаю, что без формального поведения он "открыт" для других реализаций, если бы принудительная оценка без предиката никогда даже не имела смысла.
Ответ 4
Я нашел хорошее приложение в http://blog.hasmanythrough.com/2008/2/27/count-length-size
В ActiveRecord существует несколько способов узнать, сколько записей находятся в ассоциации, и есть некоторые тонкие различия в том, как они работают.
post.comments.count - определение количества элементов с помощью SQL COUNT. Вы также можете указать условия для подсчета только подмножества связанные элементы (например: условия = > {: author_name = > "Josh" }). Если вы настроили кеш-счетчик в ассоциации, #count вернет это кэшированное значение вместо выполнения нового запроса.
post.comments.length - это всегда загружает содержимое объединение в память, а затем возвращает количество загруженных элементов. Обратите внимание, что это не будет принудительно обновлять, если ассоциация была ранее загруженные, а затем новые комментарии были созданы через другой (например, Comment.create(...) вместо post.comments.create(...)).
post.comments.size - Это работает как комбинация двух предыдущих опции. Если коллекция уже загружена, она вернет ее длина, как вызов #length. Если он еще не загружен, как вызов #count.
Также у меня есть личный опыт:
<%= h(params.size.to_s) %> # works_like_that !
<%= h(params.count.to_s) %> # does_not_work_like_that !
Ответ 5
У нас есть несколько способов узнать, сколько элементов в массиве, например .length
, .count
и .size
. Однако лучше использовать array.size
, а не array.count
. Потому что .size
лучше работает.
Ответ 6
Добавляем больше, чтобы ответить Mark Byers. В Ruby метод array.size
является псевдонимом метода Array # length. Технической разницы в использовании любого из этих двух методов нет. Возможно, вы не увидите никакой разницы в производительности. Тем не менее, array.count
также выполняет ту же работу, но с некоторыми дополнительными функциями Array # count
Он может использоваться для получения полного количества элементов, основанных на каком-либо условии. Счет можно вызвать тремя способами:
Массив # count # Возвращает количество элементов в массиве
Array # count n # Возвращает число элементов, имеющих значение n в массиве
Массив # Количество {| я | i? e?? Возвращает количество, основанное на условии, вызванном для каждого массива элементов
array = [1,2,3,4,5,6,7,4,3,2,4,5,6,7,1,2,4]
array.size # => 17
array.length # => 17
array.count # => 17
Здесь все три метода выполняют ту же работу. Однако здесь интересен count
.
Скажем, я хочу найти, сколько элементов массива содержит массив со значением 2
array.count 2 # => 3
В массиве имеется три элемента со значением как 2.
Теперь я хочу найти все элементы массива больше 4
array.count{|i| i > 4} # =>6
В массиве имеется 6 элементов, размер которых меньше 4.
Надеюсь, это даст некоторую информацию о методе count
.