148

我似乎无法找到一个明确的答案,我想确保我理解到“第 n 级”:-)

    a = { "a" => "你好", "b" => "世界" }
    a.count #2
    a.尺寸#2
    a.长度#2

    a = [ 10, 20 ]
    a.count #2
    a.尺寸#2
    a.长度#2

那么使用哪个?如果我想知道 a 是否有多个元素,那么这似乎无关紧要,但我想确保我了解真正的区别。这也适用于数组。我得到相同的结果。

另外,我意识到计数/大小/长度与 ActiveRecord 有不同的含义。我现在对纯 Ruby (1.92) 最感兴趣,但如果有人想了解 AR 带来的不同,我也将不胜感激。

谢谢!

4

6 回答 6

201

对于数组和哈希sizelength. 它们是同义词,做的事情完全相同。

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,存在重要差异。看看这篇文章:

于 2010-12-29T01:08:25.260 回答
10

使用数据库连接的应用程序有一个关键的区别。

当您使用许多 ORM(ActiveRecord、DataMapper 等)时,一般的理解是 .size 将生成一个查询,该查询从数据库中请求所有项目('select * from mytable'),然后给您项目的数量结果,而 .count 将生成一个查询('select count(*) from mytable'),这要快得多。

因为这些 ORM 如此普遍,所以我遵循最小惊讶原则。一般来说,如果我的内存中已经有一些东西,那么我使用 .size,如果我的代码将生成对数据库(或通过 API 的外部服务)的请求,我使用 .count。

于 2010-12-29T08:00:44.827 回答
7

在大多数情况下(例如ArrayStringsize.length

count通常来自Enumerable并且可以采用可选的谓词块。因此enumerable.count {cond}[大致] (enumerable.select {cond}).length——它当然可以绕过中间结构,因为它只需要匹配谓词的计数。

注意:如果未指定块,或者如果可能的话,我不确定是否count 强制对枚举进行评估length

编辑(感谢马克的回答!): count 没有块(至少对于数组)不会强制评估。我想如果没有正式的行为,它对于其他实现是“开放的”,如果强制一个没有谓词的评估甚至真的有意义的话。

于 2010-12-29T01:10:50.317 回答
5

我在http://blog.hasmanythrough.com/2008/2/27/count-length-size找到了一个很好的答案

在 ActiveRecord 中,有几种方法可以找出关联中有多少条记录,它们的工作方式有一些细微的差别。

post.comments.count - 使用 SQL COUNT 查询确定元素的数量。您还可以指定条件以仅计算关联元素的子集(例如:conditions => {: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 !
于 2011-11-20T00:37:57.300 回答
2

我们有几种方法可以找出数组中有多少元素,例如.length,.count.size。但是,最好使用array.size而不是array.count. 因为.size性能更好。

于 2016-04-06T13:02:14.950 回答
1

为 Mark Byers 的答案添加更多内容。在 Ruby 中,该方法array.sizeArray#length方法的别名。使用这两种方法中的任何一种都没有技术差异。可能您也不会看到任何性能差异。然而,array.count也做同样的工作,但有一些额外的功能Array#count

它可用于根据某些条件获取元素的总数。Count 可以通过三种方式调用:

Array#count # 返回数组中元素的个数

Array#count n # 返回数组中值为 n 的元素个数

数组#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方法的信息。

于 2016-03-15T06:07:04.157 回答