例如我有一个数组
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)。
例如我有一个数组
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)。
这也可以:
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]]
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]
) 中,除非它已经是一个数组。
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)
实现了塞尔吉奥·图伦采夫的想法
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] }