β

“茴”字的 N 种写法:关于 Ruby Array 与 Enumerable

Peek Poke 7 阅读

【词汇量?是的!编程语言也要背单词!】

Array 是最基本的数据结构之一。

对数组的操作,回忆一下,除了 .each ,你还会哪些操作?

Array 元素进行处理的操作很常见。 Array 的内置方法提供了基本的操作。然而有些场合这些方法并不够用以实现简单的处理逻辑。 好消息是可以利用 Enumerable 模块提供的方法,而这些方法容易被忽视。

判断必然性与存在性 all? / any? / none? / one?

如何判断一个数组的全部对象满足某一条件?或者任意对象满足某一条件?

all? / any? 来实现:

’’’ [true, false, 1, 0].all? ‘’’

如判断一个字符串数组的对象是否由小写字母组成:

ary = ['hello', 'world', '123']

# 判断全部满足条件,使用 each 循环
-> (ary) {
  ary.each {|s|
    return false unless s.match /[a-z]+/
  }
  return true
}.call(ary)

# map 结合 all?
ary.map {|s| s.match /[a-z]+/ }.all?

# 直接用 all? 判断
ary.all? {|s| s.match /[a-z]+/ }

# 判断任一满足条件,使用 each 循环
-> (ary) {
  ary.each {|s|
    return true if s.match /[a-z]+/
  }
  return false
}.call(ary)

# map 结合 any?
ary.map {|s| s.match /[a-z]+/ }.any?

# 直接用 any? 判断
ary.any? {|s| s.match /[a-z]+/ }

包含代码块的调用,使用代码块返回值作真假判断; 不包含传递代码块的调用,直接对数组的元素作真假判断。

先做变换,然后操作 flat_map collect_concat

each map 方法返回值如果仍为需要合并的数组,使用这个方法来减少一次 flatten 操作。

[1,2,3,4].collect{|n| [n]*n }
# => [[1], [2, 2], [3, 3, 3], [4, 4, 4, 4]]
[1,2,3,4].collect_concat{|n| [n]*n }
# => [1, 2, 2, 3, 3, 3, 4, 4, 4, 4]

数数 count

这个方法的作用很简单。

count 其实还可以接受一个参数或代码块,用于对特定的值或条件作计数。

%w{a b c d a c e}.count('a')
# => 2

%w{a b c d a c e}.count{|x| x > 'b'}
=> 4

遍历查询 find / detect

寻找第一个满足条件的值

(1..100).find    { |i| i % 5 == 0 and i % 3 == 0 }

切分

切分是一大类方法。

恰当的切分有助于使用合适的数据结构作数据操作。

分块处理 chunk

顾名思义,对数组的元素 分块 。这个方法主要用于分组处理,可以使得逻辑更加清晰。

ary = [3, 1, 4, 1, 5, 9, 2, 6, 5, 3, 5]

ary.chunk { |n| n > 3 }.to_a
# => [[false, [3, 1]], [true, [4]], [false, [1]], [true, [5, 9]], [false, [2]], [true, [6, 5]], [false, [3]], [true, [5]]]

分区 partition

根据条件分为两组

(1..6).partition {|v| v % 3 == 0 }
# => [[3, 6], [1, 2, 4, 5]]

each_cons / each_slice

适用于对相邻的元素进行操作。

这两个方法都是一次取出 n 个元素。但是取的操作有区别。

each_cons 从第 1 个元素开始去取 n 个元素,下一次从第 2 个元素开始,以此类推。 each_slice 从第 1 个元素开始去取 n 个元素,下一次从第 n + 1 个元素开始,以此类推。

(1..5).each_cons(2).to_a
# => [[1, 2], [2, 3], [3, 4], [4, 5]]
(1..5).each_slice(2).to_a
# => [[1, 2], [3, 4], [5]]

slice_before / slice_after

条件满足时,在元素之前或之后进行切分。

(1..10).slice_after{|n| n > 3}.to_a
# => [[1, 2, 3, 4], [5], [6], [7], [8], [9], [10]]
(1..10).slice_before{|n| n > 3}.to_a
# => [[1, 2, 3], [4], [5], [6], [7], [8], [9], [10]]

slice_when / chunk_while

(1..10).slice_when{|x,y| x%3 == 0 and y&2 == 0}.to_a
# => [[1, 2, 3], [4, 5, 6, 7, 8, 9, 10]]

(1..10).chunk_while{|x,y| x%3 == 0 and y&2 == 0}.to_a
# => [[1], [2], [3, 4], [5], [6], [7], [8], [9], [10]]
作者:Peek Poke

发表评论