D-1, length、size & count

很简单的一个问题,但其实了解後蛮好玩的。

When google translate

length : 长度。
size : 尺寸。
count : 计数。


When Ruby。

size&length
在阵列与Hash这种长条状的资料上,sizelength基本上一样,也可说是sizelength的别名,阵列与Hash在记忆体中,就是一条长条状的储存方式,所以长度本就比尺寸来形容更恰当。
length比size要多打2个字母啦。

2.7.3 :009 > [1, 2, 3, 4].size
 => 4
2.7.3 :010 > [1, 2, 3, 4].length
 => 4

或者该说,记忆体型态上如果是这种长条型的,lengthsize没有差别,都是能了解长度的同名方法而已了。

例如Integer这个型态就没有length,虽然一般size都是8。

2.7.3 :001 > 8.size
 => 8
2.7.3 :002 > 8.length
Traceback (most recent call last):
(irb):2:in `<main>': undefined method `length' for 8:Integer (NoMethodError)

count
lengthsizecount都是计数方法,但count在执行上不是只有计算长度或尺寸,本身也是迭代枚举产生器,可以对每一个元素作纪录或操作,没有给予条件的话回传有几个元素。所以在Ruby单纯算长度等不要用count,会稍微慢一点点。

2.7.3 :018 > [1, 2, 3, 4].count
 => 4
2.7.3 :019 > [1, 2, 3, 4].count(3)
 => 1
2.7.3 :020 > [1, 2, 3, 4].count {|num| num > 2}
 => 2

某些Class就不能直接以count计算长度(或没有此方法),只有纪录或查询功能。

2.7.3 :023 > 65.count
Traceback (most recent call last):
(irb):23:in <main>': undefined method `count' for 65:Integer (NoMethodError)

2.7.3 :024 > "abc efg abc".count
count: wrong number of arguments (given 0, expected 1+) (ArgumentError)
2.7.3 :025 > "abc efg abc".count("a")
 => 2
2.7.3 :026 > "abc efg abc".count("ac")
 => 4
2.7.3 :027 > "abc efg abc".count("efg")
 => 3

想找符合efg这样连续的吗? 请记得改用Regexp

2.7.3 :029 > "abc efg abc".match(/efg/)
 => #<MatchData "efg">

when Rails

在Rails中,这三者被讨论的部分在ActiveRecord这个部分。
lengthcount本质上不一样的方法,在有不一样用途时就该用不同的方法。

length
当如果已经load过所有资料,单纯查length的话,就该用length,而不是count,以避免再对资料库再一次进行query

2.7.3 :001 > user = User.first
  User Load (1.1ms)  SELECT "users".* FROM "users" ORDER BY "users"."id" ASC LIMIT $1  [["LIMIT", 1]]
2.7.3 :002 > user.articles.length
  Article Load (1.1ms)  SELECT "articles".* FROM "articles" WHERE "articles"."user_id" = $1  [["user_id", 1]]
 => 10

#载入过,不在需要去查询。
2.7.3 :003 > user.articles.length
 => 10

但缺点也很明显Article Load进资料库里一个一个查。


count
当如果没有load过任何资料,那就请用count来计算,count会产生SQL里的count()函数,
不需要去load

2.7.3 :001 > articles = Article.all
  Article Load (1.2ms)  SELECT "articles".* FROM "articles" /* loading for inspect */ LIMIT $1  [["LIMIT", 11]]
  
2.7.3 :002 > articles.count
   (2.9ms)  SELECT COUNT(*) FROM "articles"
 => 10
 
2.7.3 :006 > articles.length
  Article Load (0.8ms)  SELECT "articles".* FROM "articles"
 => 10

资料少时,计算可能耗时,但资料多时,就明显效能高很多,一笔一笔去读取...这跟N+1一样恐怖呀。
但缺点是每次都会计算。

2.7.3 :002 > articles.count
   (2.9ms)  SELECT COUNT(*) FROM "articles"
 => 10
2.7.3 :003 > articles.count
   (0.9ms)  SELECT COUNT(*) FROM "articles"
 => 10
2.7.3 :004 > articles.count
   (3.3ms)  SELECT COUNT(*) FROM "articles"
 => 10
2.7.3 :005 > articles.count
   (1.3ms)  SELECT COUNT(*) FROM "articles"
 => 10

缺点中的优点是准确,每算一次都会检查一次。


size
它不再是谁的别名了,它可以协助你视情况用lengthcount,应该说会帮你判断要去读取还是计数。定义类似如下。

def size
  loaded? ? @jobs.length : count
  # if loaded?
      #@jobs.length
    #else
      #@jobs.count
    #end
end

这是个让你不用去苦恼用lengthcount的好帮手,但是使用这种自动功能,总有个小缺点,当你还是明确希望去countlength时,它可能给你执行相反的状况,因为size不是由你决定用哪个,而是看有没有loaded

YA!明天最後一天啦!


<<:  [Angular] Day29. Internationalization (i18n)

>>:  # Day14--解决暧昧问题延伸出来的那些事

Observer 观察者模式

今天要谈到的观察者模式也是很常见的一个模式,常出现在有两个以上需要互相沟通的物件之间 问题 假设有个...

Day3 条件判断

今天来学学Vue里面的判别式v-if 跟v-show 1.v - if 在这里我们将条件设定为Sho...

Day 11:Python基本介绍04 | Set、Dictionary

おはよう~昨天我们介绍完了四种Collections的其中两种 - List、Tuple,而今天要接...

Day22_CSS语法5

font-style属性设定HTML元素的文字样式 normal : 正常(预设值) italic ...

android studio 30天学习笔记-day 8-基本介绍rxjava2

RxJava2是一套处理非同步(asynchronous)事件的library,这个library是...