Enumerable Module 里面比较实用的方法

Enumerable module 里面有很多实用的方法,可能有些方法,我们不是很熟悉。 如果知道的话,可能对于改善我们的代码会有所帮助。我这边提取了几个比较实用的 方法供大家参考。(注意本文是 Ruby 2.2.0 版本测试的结果)

chunk {|elt|…}

chunk 方法会将根据 block 里面表达式的返回值分组处理,注意只会分组连续的元素。 例如:

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

注意 block 返回值里面是 nil 或 :_separator 的话,表示这个元素将会被删除掉, 对于过滤元素非常实用。 如果读文件的内容的时候,想忽略空行的时候可以使用这个方法过滤。

1
2
3
4
5
6
7
8
[3, 1, 4, 1, 5, 9, 2, 6, 5, 3, 5].chunk { |n| n > 5 || nil }.to_a
=> [[true, [9]], [true, [6]]]

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

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

还有一个比较特别的 :_alone 表达式表示自己独立分组不和别的元素在一起。 例子:

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

[3, 9, 10, 2, 6, 7].chunk { |n| n > 5 ? :_alone : true }.to_a
=> [[true, [3]], [:_alone, [9]], [:_alone, [10]], [true, [2]], [:_alone, [6]], [:_alone, [7]]]

在 rails 开发中也会经常遇到使用 chunk 的情况,例如:想把用户按照月份分组显示出来。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
- @users = User.order('created_at desc')

%h1 User Monthly Breakdown

- @users.chunk { |u| u.created_at.strftime("%B %Y") }.each do |month, users|
  %h3= month
  %table.table
    %thead
      %tr
        %th Name
        %th Email

    - users.each do |user|
      %tr
        %td= user.name
        %td= user.email

partition { |obj| block }

将一个集合根据 block 的返回值,分割成2个。

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

max_by, min_by, minmax_by

从名字上就可以猜出来是用来取最大最小值的。

1
2
3
4
5
a = %w(albatross dog horse)
a.max                        #=> "horse"
a.max_by { |x| x.length }   #=> "albatross"
a.min_by { |x| x.length }   #=> "dog"
a.minmax_by { |x| x.length }   #=> ["dog", "albatross"]

zip

将 enum 每个元素和参数的每个对应元素合并。 例子:

1
2
3
4
5
6
a = [ 4, 5, 6 ]
b = [ 7, 8, 9 ]

[1, 2, 3].zip(a, b)      #=> [[1, 4, 7], [2, 5, 8], [3, 6, 9]]
[1, 2].zip(a, b)         #=> [[1, 4, 7], [2, 5, 8]]
a.zip([1, 2], [8])       #=> [[4, 1, 8], [5, 2, nil], [6, nil, nil]]

评论