0

例如我有一个数组

g = [0,0,0,1,1,1,0,1,1,0,0,1,0,0,1,1,1,1,0,0,0,1,1,1]

结果我需要

f = [0,0,0,[1,1,1],0,[1,1],0,0,1,0,0,[1,1,1,1],0,0,0,[1,1,1]]

仅当元素按顺序出现两次或多次时才需要连接元素 (1)。

4

4 回答 4

3

这也可以:

g.chunk{ |e| e }.flat_map { |a, b| a == 0 || b.length == 1 ? b : [b] }
#=> [0, 0, 0, [1, 1, 1], 0, [1, 1], 0, 0, 1, 0, 0, [1, 1, 1, 1], 0, 0, 0, [1, 1, 1]]
于 2013-07-24T13:01:47.917 回答
1
g.inject([]) do |ary, i|
  if i == 0 or ary.last == 0
    ary << i
  else
    ary[-1] = Array(ary.last) << i
    ary
  end
end

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

这应该在 O(n) 运行时。

仅供参考:Array(thing)包装thing在一个数组 ( [thing]) 中,除非它已经是一个数组。

于 2013-07-24T12:21:01.337 回答
1

Enumerable#chunk将是一个很好的选择。

g = [0,0,0,1,1,1,0,1,1,0,0,1,0,0,1,1,1,1,0,0,0,1,1,1]
p g.chunk{|i| i == 0}.to_a
# >> [[true, [0, 0, 0]], [false, [1, 1, 1]], [true, [0]],
# [false, [1, 1]], [true, [0, 0]], [false, [1]],
# [true, [0, 0]], [false, [1, 1, 1, 1]], 
# [true, [0, 0, 0]], [false, [1, 1, 1]]]
ar = g.chunk{|i| i == 0}.each_with_object([]) do |(e1,e2),a|
    (!e1 && e2.size > 1) ? a.concat([e2]) :  a.concat(e2)
end
p ar
# >> [0, 0, 0, [1, 1, 1], 0, [1, 1], 0, 0, 1, 0, 0, 
#    [1, 1, 1, 1], 0, 0, 0, [1, 1, 1]

基准

require 'benchmark'

g = [0,0,0,1,1,1,0,1,1,0,0,1,0,0,1,1,1,1,0,0,0,1,1,1]
n = 1000000
Benchmark.bm(15) do |x|
  x.report('stefan') { n.times { g.chunk{ |e| e }.flat_map { |a, b| a == 0 || b.length == 1 ? b : [b] } } }
  x.report('priti') { n.times { g.chunk{|i| i == 0}.each_with_object([]){|(e1,e2),a| (!e1 && e2.size > 1) ? a.concat([e2]) :  a.concat(e2)} } }
  x.report('tessi') { n.times { g.inject([]) { |ary, i| (i == 0 or ary.last == 0) ? ary << i : (ary[-1] = Array(ary.last) << i); ary }}}
end

                      user     system      total        real
stefan           11.860000   0.000000  11.860000 ( 11.890553)
priti            13.360000   0.000000  13.360000 ( 13.406585)
tessi             5.650000   0.000000   5.650000 (  5.666377)
于 2013-07-24T12:37:53.490 回答
0

实现了塞尔吉奥·图伦采夫的想法

g = [0,0,0,1,1,1,0,1,1,0,0,1,0,0,1,1,1,1,0,0,0,1,1,1]
f = []
ones = []
g.each { |x|
  if x == 1
    ones << x
  else
    if ones.size > 1
      f << ones
    elsif ones.size == 1
      f += ones
    end
    ones = []
    f << x
  end
}
if ones.size > 1
  f << ones
elsif ones.size == 1
  f += ones
end

更新

选择

g = [0,0,0,1,1,1,0,1,1,0,0,1,0,0,1,1,1,1,0,0,0,1,1,1]
f = []
g.each { |x|
  if x == 1
    f << [] if ! f.last.is_a? Array
    f.last << x
  else
    f << x
  end
}
f.each_with_index { |x,i| f[i] = 1 if x == [1] }
于 2013-07-24T11:42:50.350 回答