3

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

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

所以我最终将其作为一个新数组...

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

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

4

6 回答 6

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]]
于 2015-05-08T19:23:35.387 回答
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]]
于 2015-05-08T19:06:19.823 回答
2

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

以下是我将如何去做:

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

#each_with_object方法允许我迭代数组,同时使用一个对象来存储我沿途收集的任何数据(该对象分配了变量n,它代表“ new_array ”)。

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

我使用两个内联if:else语句,使用简写:

condition ? do_if_true : do_if_false

对一些答案进行基准测试

在我的 MacBook Pro 上测试了一些答案,看来我的方法是迄今为止最快的……但也许我有偏见。

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

两个最佳结果以粗体显示

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

                    user     system      total        real

@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 )

基准代码

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

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

require 'benchmark'

[10, 100, 1000, 10000].each do |items|

  a = (Array.new(items) { rand 2 })
  cycles = 1_000_000 / items

  puts "report for array with #{items} items, #{cycles} iterations:"

  Benchmark.bm do |bm|
    bm.report("@tykowale's approach") {cycles.times { a.split_by {|x| x == 0} } }
    bm.report("@infused's approach") {cycles.times { a.join.split(/0/).map {|group| group.split(//).map(&:to_i) unless group == ''}.compact } }
    bm.report("@CarySwoveland's approach") { cycles.times { a.chunk(&:itself).select { |a| a.first==1 }.map(&:last) } }
    bm.report("@Myst's approach") { cycles.times { a.each_with_object([[]]) {|i, n| i == 1 ? ( n.last << i) : (n.last.empty? ? true : (n << [])) } } }
    bm.report("@Sid's approach") { cycles.times { a.chunk {|x| x==1 || nil}.map{|y,ys| ys} } }
  end
end
于 2015-05-08T19:10:04.140 回答
1

这是使用Enumerable#chunk的一种方法:

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

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

a.slice_when { |bef,aft| bef!=aft }.reject { |e| e.first != 1 }
  #=> [[1, 1], [1], [1, 1, 1]]
于 2015-05-08T19:10:44.493 回答
1

您可以将其修补为 enumerable 并将其传递给一个块,这样它就可以更多地用于您想要的任何数字或表达式

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]]

根据值从拆分数组中找到(大部分)这个子数组

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

于 2015-05-08T19:14:06.020 回答
0
a.join.split('0').select {|b| b if not b.empty?}.map {|c| c.split(//).map{|d| d.to_i}}
于 2015-05-08T19:59:05.193 回答