Enumberable中的三个method。
用途:
把一个enum拆分,最后返回一个enumerator,拆分的位置怎么定?循环enum中的元素,执行给到的block或者Pattern,当返回为true时,该element的位置就是拆分的位置。
slice_before, slice_after非常相似,可以接受block或者Pattern,区别仅在于拆分位置是在匹配元素的前面还是后面,而slice_when 只接受block作为参数,而且block中,需要有两个arguments。
官方文档中,给出了好些例子,感觉有点过于复杂,对我这种新手来说,不大友好:P
这里直接用最简单的例子来说明下它们三个的基本使用。
使用:
[以下代码基于Ruby 2.4]
例子:
demo = [1, 'a', 2, 'b', 'c', 3, 'd', 'e', 'f']
demo.slice_before { |e| e.is_a?(Integer)}.to_a
# => [[1, "a"], [2, "b", "c"], [3, "d", "e", "f"]]
demo.slice_before(Integer).to_a
# => [[1, "a"], [2, "b", "c"], [3, "d", "e", "f"]]
## after 基本类似,只是从匹配元素后开始拆分
demo.slice_after { |e| e.is_a?(Integer)}.to_a
# => [[1], ["a", 2], ["b", "c", 3], ["d", "e", "f"]]
demo.slice_after(Integer).to_a
# => [[1], ["a", 2], ["b", "c", 3], ["d", "e", "f"]]
demo.slice_when {|x, y| x.is_a?(Integer)}.to_a
# => [[1], ["a", 2], ["b", "c", 3], ["d", "e", "f"]]
这里的Pattern是Integer,有必要提一下Pattern === elt。
slice_before, slice_after可以 使用Pattern === elt, 不过===
这个method在ruby的不同Object中,有着不一样的定义。ruby doc中的解释是:
Behavior of the ===
method varies for each Object.
在Object这个类中,===类似于#==,我的理解是, Object中的===,类似于elt.is_a?(Pattern)
比如:
Integer === 1
# => true
Integer === :hello ## :hello 是一个symbol
# => false
在Regexp正则中,如果elt匹配pattern,则返回true,而在ruby2.5的文档中,对于Set类,===则是includes?的别名方法。如:
Set[1,2,3] === 2 ## true
Set[1,2,3] === 4 ## false
此外,上面的例子中,slice_when的执行结果与slice_after一样,呃,举的例子不好。
slice_when的block中,接受的两个参数,一个是current element,一个是previous element。 它在拆分出连续型数组部分很有用,看例子:
demo = [1, 3, 4, 5, 7, 8, 9, 10, 12]
demo.sort.slice_when { |a, b| a + 1 != b }.to_a
# => [[1], [3, 4, 5], [7, 8, 9, 10], [12]]
也可以用来找出数组中重复数据及其对应的重复个数:
demo = [1, 2, 3, 1, 1, 2, 3, 2, 2, 2, 3, 1]
demo.sort.slice_when(&:!=).map { |x| { x.first => x.count} }
# => [{1=>4}, {2=>5}, {3=>3}]
OK。