Ruby - 枚举 Enumerable (一)
Varsion

所有集合类型对象的创建都不一样,但是他们中大多数都有共通的特性。在Ruby中,集合类型对象通常都包含Enumerable模块。

使用Enumerable的类有一种协定:该类必须定义一个名为each的实例方法,而同时该模块也赋予了该类一组集合类型的相关行为。

1
2
3
4
5
6
class C
include Enumerable
def each
# code
end
end

依赖each获得枚举能力

任何可枚举的类都具有一个each方法(必须)。其作用是将其中的元素逐个的做为参数传递给代码块(yield

  • 在数组中,each依次传递各个元素给代码块
  • 在哈希中,则是以两个元素的数组来传递键值对
  • 在文件处理的情况下,会依次传递文件中的第一行给代码块
  • 范围则会首先判断迭代是否可用(如起点是浮点数的情况)然后会伪装成数组进行传递

而如果在自己的类中定义了each方法,就可以将其自定义,只要传递参数给代码块即可

但是无论怎样,只要实现了each,就可以通过他来调用Enumerab模块中的方法

1
2
3
4
5
6
7
8
9
10
11
12
class Rainbow
include Enumerable
def each
yield "red"
yield "orange"
yield "yellow"
yield "green"
yield "blue"
yield "indigo"
yield "violet"
end
end

Rainbow的每个实例都可以迭代这些函数,最简单的情况下可以这样使用each来遍历所有元素

1
2
3
Rainbow.new.each do color
puts "Color is #{color}"
end

可枚举对象的搜索和选择

Enumerable提供了很多功能,可用于在集合类型对象中根据一些条件过滤和搜索其中的一个或多个元素

这些条件过滤和搜索方法中,所使用的全都是迭代器,全都需要提供一个代码块,而这个代码块就是一个选择过滤器,可以在该代码块中定义自己的过滤条件.整个方法的返回值也会不相同,可能会返回一个对象,一个包含匹配对象的数组(数组可能为空)或者没有任何条件匹配时返回nil

使用find方法进行第一次匹配

通过将数组中的元素作为参数传递个代码块并执行条件判断

find(还有一个可用的同义方法detect)会定位数组中第一个条件判断为真的元素例如

1
[1,2,3,4,5,6,7,8].find {n n>5}

这行代码会返回6,即第一个符合条件判断为真的元素

find迭代整个数组,将每个元素依传递到代码块中.如果代码使用布尔值为真的形式作为返回值,那么当前的元素就获得了优先,find代码就会停止迭代,如果find并没有查找到符合的元素,将会返回nil

而如果只是为了测试该数组或者该对象中是否存在一个值,更建议的方法是使用include

1
[1,2,3,4,nil,5,6].find {n n.nil?}

如果在当前情境下使用find方法,无论是否存在元素为nil该代码都将返回nil这个时候include更能解决问题array.include?nil

find_allreject获取所有匹配元素

find_all又名select会返回一个新集合类型的对象,其中包含了在代码块中所有匹配从原始集合类型对象中得到的元素,而不仅仅是第一个匹配到的元素

如果没有匹配到任何元素,会返回一个空类型集合对象

1
[1,2,3,4,5,6,7,8,9].find_all {n n>5 }

这段代码会返回[6,7,8,9]即原数组中所有符合n>5的元素

同时数组,散列,集合都有select!的bang方法版本,会让源集合只留下条件判断为真的数据,不过不存在find_all!必须使用select!

reject方法可以排除元素,即将所有符合条件判断的数据剔除

同时,reject存在bang方法reject!会直接在源数据上修改.适用于数组,哈希,集合

基于三等号匹配的grep来选择元素

Enumerab#grep方法会基于case的相等性运算符===,从可枚举对象中选择元素,grep最常见的用户,即字符串匹配模式

grep的普遍性可以让我们做一些花哨的工作

1
2
3
array.grep(/o/)      # 利用正则匹配元素
array.grep(String) #利用类型匹配元素
array.grep(50..100) #利用范围匹配元素

总言之array.grep(expression)等同于:

1
array.select [ element expression === element}

group_bypartition

group_by操作包含一个代码块并返回一个散列

对于每个对象,代码块都会被执行一次,每个独立代码块返回的值,最终会作为返回值的散列键,而键对应的值则是一个数组,该数组的元素包含哪些可枚举对象中的元素是通过代码的返回值来确定的.

1
2
colors = %w{red orange yellow green blue}
colors.group_by {color color.size}

改代码的返回值则是如下的散列

根据其字符串的长度来分组

partition会基于代码块是否返回为真,来将可枚举对象的元素分割为两个数组

1
[1,2,3,4,5,6,7,8].partition {x x%2 == 0}


  • Post title:Ruby - 枚举 Enumerable (一)
  • Post author:Varsion
  • Create time:2020-09-18 11:06:32
  • Post link:https://blog.varsion.cn/post/f285573c.html
  • Copyright Notice:All articles in this blog are licensed under BY-NC-SA unless stating additionally.
Comments