Кажется, я не могу найти окончательного ответа по этому поводу, и я хочу убедиться, что понимаю это до «n-го уровня» :-)
a = {"a" => "Привет", "b" => "Мир"} a.count # 2 а. размер # 2 а. длина # 2 а = [10, 20] a.count # 2 а. размер # 2 а. длина # 2
Итак, что использовать? Если я хочу знать, имеет ли a более одного элемента, то это не имеет значения, но я хочу убедиться, что понимаю реальную разницу. Это относится и к массивам. Я получаю такие же результаты.
Кроме того, я понимаю, что количество / размер / длина имеют разные значения в ActiveRecord. Сейчас меня больше всего интересует чистый Ruby (1.92), но если кто-то захочет узнать о разнице, которую делает AR, это тоже будет признательно.
Благодарность!
ruby
activerecord
size
content-length
cbmeeks
источник
источник
Array#nitems
который возвращает количество элементов, отличных от NIL, в массиве. Но это больше не доступно в Ruby 1.9Ответы:
Для массивов и хэшей
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, с другой стороны, есть существенные различия. посмотрите этот пост:
источник
Существует критическая разница для приложений, использующих соединения с базой данных.
Когда вы используете много ORM (ActiveRecord, DataMapper и т. Д.), Общее понимание состоит в том, что .size будет генерировать запрос, который запрашивает все элементы из базы данных ('select * from mytable'), а затем дает вам количество элементов в результате, тогда как .count будет генерировать один запрос ('select count (*) from mytable'), что значительно быстрее.
Поскольку эти ORM настолько распространены, я следую принципу наименьшего удивления. В общем, если у меня что-то уже есть в памяти, я использую .size, а если мой код генерирует запрос к базе данных (или внешней службе через API), я использую .count.
источник
counter_cache
. Если есть таблица,foo
и has_manybar
, у вас будет столбец сfoo
именем,bars_count
который обновляется каждый раз, когдаbar
создается / уничтожается. Использованиеfoo.bars.size
- это то, что проверяет этот столбец (без фактического запросаbars
).foo.bars.count
выполняет фактический запрос, который нарушил бы цель кеша.В большинстве случаев (например, Array или String )
size
- это псевдоним дляlength
.count
обычно поступает из Enumerable и может принимать необязательный блок предикатов. Таким образомenumerable.count {cond}
, [примерно](enumerable.select {cond}).length
- он, конечно, может обойти промежуточную структуру, поскольку ему просто нужен подсчет совпадающих предикатов.Примечание: я не уверен,
count
заставляет ли выполнять оценку перечисления, если блок не указан, или если он замыкается на,length
если это возможно.Изменить (и спасибо за ответ Марка!):
count
Без блока (по крайней мере, для массивов) не вызывает оценку. Я полагаю, что без формального поведения он «открыт» для других реализаций, если принудительное вычисление без предиката вообще имеет смысл.источник
Я нашел хорошее программное обеспечение на http://blog.hasmanythrough.com/2008/2/27/count-length-size
Также имею личный опыт:
<%= h(params.size.to_s) %> # works_like_that ! <%= h(params.count.to_s) %> # does_not_work_like_that !
источник
У нас есть несколько способов узнать, сколько элементов в массиве, например
.length
,.count
и.size
. Однако лучше использоватьarray.size
, чемarray.count
. Потому.size
что лучше по производительности.источник
Добавляем еще к ответу Марка Байерса. В Ruby этот метод
array.size
является псевдонимом метода Array # length . Нет никакой технической разницы в использовании любого из этих двух методов. Возможно, вы не заметите и разницы в производительности. Тем не менее, онarray.count
также выполняет ту же работу, но с некоторыми дополнительными функциями. Array # countЕго можно использовать для получения общего количества элементов на основе некоторого условия. Счетчик можно вызвать тремя способами:
Array # count # Возвращает количество элементов в массиве
Array # count n # Возвращает количество элементов, имеющих значение n в массиве
Массив # count {| i | ieven?} Возвращает количество на основе условия, установленного для каждого массива элементов.
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
методе.источник