微信号:rigongyizu365

介绍:一线码农不端不装的「日拱一卒」,关注技术、书籍、创业、GTD、以及一切个人成长周边的话题,每周一到五更新.

集合使用的技巧(二) | Ruby

2016-09-12 23:50 lazybios

使用集合高效检查元素包容性

ArrayHash不同,Set虽然结构虽然也是Ruby自带的,但其不在核心库之列,属于标准库,使用的时候需要预先通过require ‘set’引入。

require 'set'

class Role
  def initialize(name, permissions)
    @name, @permissions = name, Set.new(permissions)
  end

  def can?(permission)
    @permissions.include?(permission)
  end
end

所有集合中,Array的include?方法的性能是最差的,其时间复杂度是O(n),当数组中的元素增加时,检查元素的存在性的时间也会变长。于此相比,访问Hash结构中的元素的时间复杂度为O(logn),而Set类的内部就是通过Hash结构存储的,所以使用Set访问时间上带来优势,不过这种优势要牺牲一些存储空间。

因为集合的无序性,所以Set是不能保证元素次序的,如果一定要求顺序,那么可以使用SortedSet集合。

通过Redcue方法折叠集合

之前发过一篇关于reduceinject的文章,不熟悉用法的同学可以从这里跳(《 一次搞懂Reduce,Inject方法》),这里直接看示例吧。

假设有一个用户数组,我们希望从中筛选出年龄大于或等于21岁的用户,并将用户名到一个数组中返回。

常规做法
users.select {|u| u.age >= 21}.map {&:name}
使用reduce
users.reduce([]) do |names, user|
  names << user.names if user.age >= 21
  names
end

使用select、map组合的方法,显然需要两次循环,但同样的效果使用reduce仅一次迭代就够了。

reduce允许省略累加器的起始值。当不给起始值时,reduce会将集合中的第一个元素作为累加器的起始值并从第二个元素开始迭代的生命周期。潜在的问题是,当你要处理一个不确定的集合时,并且它有可能是一个空集合,那么就会有一定的概率返回nil值。当然,如果你可以正常处理nil这个就不算啥问题了。

reduce会在一次迭代后,丢弃上一次迭代的累加器并保留了块的返回值作为新的累加器。你可以通过块的返回值来控制累加器,原则上它可以是任意值。

-待续-

你还可以看:

什么是康威定律 | 三分钟

使用Retry处理异常的套路

Ruby: 一次搞懂Reduce,Inject方法

参考引用


 
日拱一卒 更多文章 Objective-C中的块(block)语法初步 MPMoviePlayerController视频播放器初步 UIViewController(视图控制器)的生命周期 关于SQL中的Join Vim中的搜索与替换
猜您喜欢 去哪儿网 MySQL 语法审核工具 Inception 正式开源I Android中自定义视图View之---进阶篇(Canvas的使用) Broadcast Receiver详解 “监狱”释放 Jmeter 利用User Defined Variables实现变量重用