Количество, размер, длина...слишком много вариантов в 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



Так что же использовать? Если я хочу знать, имеет ли a более одного элемента, то это не имеет значения, но я хочу убедиться, что понимаю реальную разницу. Это относится и к массивам. Я получаю те же результаты.



кроме того, я понимаю, что count/size/length имеют разные значения с ActiveRecord. Я в основном интересовался чисто Ruby (1.92) прямо сейчас, но если кто-то хочет вмешаться в разницу, которую делает AR, это также будет оценено.



спасибо!

797   6  

6 ответов:

для массивов и хэшей size псевдоним length. Они являются синонимами и делают точно то же самое.

count является более универсальным - он может принимать элемент или предикат и считать только те элементы, которые соответствуют.

> [1,2,3].count{|x| x > 2 }
=> 1

в том случае, когда вы не укажите параметр для подсчета он имеет в основном тот же эффект, что и длина вызова. Там может быть разница в производительности хотя.

мы можем видеть из исходный код для массива что они делают почти то же самое. Вот код 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, с другой стороны, там are важные различия. проверьте это сообщение:

существует важное различие для приложений, которые используют подключения к базе данных.

когда вы используете много ORMs (ActiveRecord, DataMapper и т. д.) общее понимание таково .размер будет генерировать запрос, который запрашивает все элементы из базы данных ('select * from mytable'), а затем дать вам количество элементов в результате, тогда как .count будет генерировать один запрос ('select count (*) from mytable'), который значительно быстрее.

потому что эти Ормы настолько распространены, что я следую принципу наименьшего удивления. Вообще если у меня что-то в памяти уже есть, то я пользуюсь .размер, и если мой код будет генерировать запрос к базе данных (или внешней службе через API) я использую .рассчитывать.

в большинстве случаев (например,массив или строка)size Это псевдоним на length.

count обычно наступает от перечисли и может принимать дополнительный блок предикатов. Таким образом enumerable.count {cond} - это [примерно] (enumerable.select {cond}).length -- он может, конечно, обойти промежуточную структуру, поскольку ему просто нужно количество совпадающих предикатов.

примечание: Я не уверен, если countсил оценка перечисление, если блок не указан или если он замыкается на length если это возможно.

редактировать (и благодаря ответу Марка!):countбез блока (по крайней мере для массивов) не силу оценки. Я полагаю, что без формального поведения он "открыт" для других реализаций, если принуждение оценки без предиката когда-либо даже действительно имеет смысл.

Я нашел хороший answare в http://blog.hasmanythrough.com/2008/2/27/count-length-size

в ActiveRecord есть несколько способов узнать, сколько записей в ассоциации, и есть некоторые тонкие различия в том, как они работают.

пост.комментарии.count-определяет количество элементов с помощью SQL Подсчет запросов. Вы также можете указать условия для подсчета только подмножества связанные элементы (например: условия => {:имя автора>= "подшучивать.)}" Если вы настроили кэш счетчиков в ассоциации, #count возвращает это кэшированное значение вместо выполнения нового запроса.

пост.комментарии.длина - это всегда загружает содержимое ассоциация в память, затем возвращает количество загруженных элементов. Обратите внимание, что это не приведет к принудительному обновлению, если связь была ранее загруженные, а затем новые комментарии были созданы через другой способ (например, комментарий.создавать.(..) вместо того должность.комментарии.создавать.(..)).

пост.комментарии.размер - это работает как комбинация двух предыдущих опции. Если коллекция уже была загружена, она вернет ее длина так же, как вызов #length. Если он еще не был загружен, это например, вызов #count.

также у меня есть личный опыт:

<%= 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.count также делает ту же работу, но с некоторыми дополнительными функциями массив#count

он может быть использован, чтобы получить полное отсутствие элементов на основе некоторых условий. Счет можно назвать в три способы:

массив#count # возвращает количество элементов в массиве

массив#count n # возвращает количество элементов, имеющих значение N в массиве

Array#count {|i / i.even?} возвращает счетчик на основе условия, вызванного на каждом элементе массива

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 метод.

Comments

    Ничего не найдено.