ruby - 当值更改时将数组拆分为子数组,并忽略/删除该值

时间:2015-05-08 18:53:21

标签: arrays ruby split sub-array

我想将以下数组拆分为子数组,以便在1的开始和结束时子数组开始和结束......

a=[1,1,0,0,1,0,1,1,1]

所以我最终把它作为一个新数组......

=>  [[1,1],[1],[1,1,1]]

任何人都有任何想法......?

6 个答案:

答案 0 :(得分:4)

最简单,最易读的方式可能是:

a.chunk {|x| x==1 || nil}.map(&:last)
  #=> [[1, 1], [1], [1, 1, 1]]

如果你可以使用Ruby on Rails,你可以使用更简单的解决方案:

a.split(0).reject(&:empty?)
  #=> [[1, 1], [1], [1, 1, 1]]

答案 1 :(得分:2)

有很多方法可以实现这一目标。一种方法是将数组转换为字符串,拆分组并将其重新映射为数组(忽略任何空组):

a=[1,1,0,0,1,0,1,1,1]
a.join.split(/0/).map {|group| group.split(//).map(&:to_i) unless group == ''}.compact
#=> [[1,1],[1],[1,1,1]]

答案 2 :(得分:1)

我喜欢许多不同的答案!所以我花时间去测试其中的一些。

以下是我的意思:

new_array = a.each_with_object([ [] ]) {|i, n| i == 1 ? ( n.last << i) : (n.last.empty? ? true : (n << []))}

#each_with_object方法允许我迭代数组,同时使用对象存储我沿途收集的任何数据(对象分配变量n,代表' n ew_array')。

在这种方法中,我将数据收集到一个嵌套数组[ [] ]的数组中,当它们被识别时添加1到最后一个嵌套数组n.last << i并添加一个新的空嵌套数组{{1}如果数据不是我想收集的数据(并且现有的嵌套数组不为空)。

我使用两个内联n << []语句,使用简写:

if:else

对一些答案进行基准测试

在我的MacBook Pro上测试一些答案,看来我的方法到目前为止是最快的......但也许我有偏见。

关于报告的注意事项:结果以秒为单位。越少越快。

两个最佳结果是粗体

报告包含10个项目,100,000次迭代的数组:

condition ? do_if_true : do_if_false

@ tykowale的方法0.210000 0.000000 0.210000( 0.209799

@ infused的方法1.300000 0.010000 1.310000(1.304084)

@ CarySwoveland的方法0.830000 0.000000 0.830000(0.839012)

@Myst的方法0.170000 0.000000 0.170000( 0.169915

@ Sid的方法0.590000 0.000000 0.590000(0.595671)

包含100个项目,10,000次迭代的数组的报告:

                    user     system      total        real

@ tykowale的方法0.160000 0.000000 0.160000( 0.155997

@ infused的方法1.030000 0.000000 1.030000(1.030392)

@ CarySwoveland的方法0.420000 0.010000 0.430000(0.424801)

@Myst的方法0.150000 0.000000 0.150000( 0.143403

@ Sid的方法0.260000 0.000000 0.260000(0.255548)

包含1,000个项目,1,000次迭代的数组的报告:

                    user     system      total        real

@ tykowale的方法0.150000 0.000000 0.150000( 0.160459

@ infused的方法1.030000 0.000000 1.030000(1.033616)

@ CarySwoveland的方法0.310000 0.000000 0.310000(0.312325)

@Myst的方法0.130000 0.000000 0.130000( 0.133339

@ Sid的方法0.210000 0.000000 0.210000(0.217960)

报告包含10,000个项目,100次迭代的数组:

                    user     system      total        real

@ tykowale的方法0.250000 0.000000 0.250000(0.252399)

@ infused的方法1.020000 0.000000 1.020000(1.017766)

@ CarySwoveland的方法0.320000 0.000000 0.320000(0.321452)

@Myst的方法0.130000 0.000000 0.130000( 0.128247

@ Sid的方法0.210000 0.000000 0.210000( 0.212489

基准代码

以下是用于基准测试的脚本:

                    user     system      total        real

答案 3 :(得分:1)

这是使用Enumerable#chunk的方式:

a.chunk { |n| n==1 }.select(&:first).map(&:last)
  #=> [[1, 1], [1], [1, 1, 1]] 

另一个是使用Enumerable#slice_when,它是在v2.2中引入的:

a.slice_when { |bef,aft| bef!=aft }.reject { |e| e.first != 1 }
  #=> [[1, 1], [1], [1, 1, 1]]

答案 4 :(得分:1)

您可以将其修补为可枚举并将其传递给一个块,以便更多可用于您想要的任何数字或表达

module Enumerable
  def split_by
    result = [a=[]]
    each{ |o| yield(o) ? (result << a=[]) : (a << o) }
    result.delete_if { |a| a.empty? }
  end
end

a=[1,1,0,0,1,0,1,1,1]

p a.split_by {|x| x == 0}
#=> [[1,1],[1],[1,1,1]]

Split array into sub-arrays based on value

中找到(大部分)此内容

编辑:更改删除空集的工作方式result.pop if a.empty?并从结尾删除不必要的结果行

答案 5 :(得分:0)

a.join.split('0').select {|b| b if not b.empty?}.map {|c| c.split(//).map{|d| d.to_i}}