问题:
- 给定Ruby中的一个数字数组,返回出现在1和2之间的数字组
- 数字1和2不出现在其他1和2之间(不存在子集的子集(
示例1
输入:[1, 3, 2, 1, 4, 2]
输出:[[1, 3, 2], [1, 4, 2]]
示例2
input: [0, 1, 3, 2, 10, 1, 5, 6, 7, 8, 7, 5, 2, 3, 1, -400, 2, 12, 16]
output: [ [1, 3, 2], [1, 5, 6, 7, 8, 7, 5, 2], [1, -400, 2] ]
我的直觉是使用#chunk
和#drop_while
的组合或生成器。
提前谢谢。
这是一个使用[Enumerable#slice_when][1]的选项:
ary1 = [1, 3, 2, 1, 4, 2]
ary2 = [0, 1, 3, 2, 10, 1, 5, 6, 7, 8, 7, 5, 2, 3, 1, -400, 2, 12, 16]
例如:
stop = [1, 2]
ary2.slice_when{ |e| stop.include? e }
.each_slice(2).map { |a, b| b.unshift(a.last) if b }
.reject { |e| e.nil? || (e.intersection stop).empty? }
#=> [[1, 3, 2], [1, 5, 6, 7, 8, 7, 5, 2], [1, -400, 2]]
其他选项
更详细但更清晰,给出输入:
input = %w(b a b c a b c a c b c a c a)
start = 'a'
stop = 'b'
使用Enumerable#each_with_object
,为什么不使用好的旧if then else
?:
tmp = []
pickup = false
input.each_with_object([]) do |e, res|
if e == start
pickup = true
tmp << e
elsif pickup && e == stop
tmp << e
res << tmp
tmp = []
pickup = false
elsif pickup
tmp << e
end
end
#=> [["a", "b"], ["a", "b"], ["a", "c", "b"]]
[1]: https://ruby-doc.org/core-2.7.0/Enumerable.html#method-i-slice_when
听起来像是一个面试问题。我将解释我能想到的最简单的算法:
您在数组中循环一次,并在执行过程中构建输出。当遇到1
时,将其和后续数字存储到另一个临时数组中。当遇到2
时,将数组放入输出数组中。边缘情况是:
- 开始构建临时阵列后的另一个
1
- 当没有临时数组时为
2
第一种情况很简单,当遇到1
时,总是构建一个新的临时数组。对于第二个,您必须检查临时数组中是否有任何项,并且只有在临时数组不为空时才将其附加到输出中。
这应该会让你开始。
您可以使用chunk
和Ruby的触发器运算符:
input = [0, 1, 3, 2, 10, 1, 5, 6, 7, 8, 7, 5, 2, 3, 1, -400, 2, 12, 16]
input.chunk { |i| true if i==1..i==2 }.each { |_, ary| p ary }
输出:
[1, 3, 2]
[1, 5, 6, 7, 8, 7, 5, 2]
[1, -400, 2]
对于所有想在海滩上散步但由于明显原因不能的人:
class Flipflop
def initialize(flip, flop) #flip and flop being boolean-returning lambdas
@state = false
@flip = flip
@flop = flop
end
def flipflop(x) #logic taken from The Ruby Programming Language page 111
if !@state
result = @flip[x]
if result
@state = !@flop[x]
end
result
else
@state = !@flop[x]
true
end
end
end
ff = Flipflop.new( ->(x){x == 1}, ->(x){x == 2} )
input = [0, 1, 3, 2, 10, 1, 5, 6, 7, 8, 7, 5, 2, 3, 1, -400, 2, 12, 16]
res = input.select{|el| ff.flipflop(el) }.slice_before(1) #an Enumerator
p res.to_a
# =>[[1, 3, 2], [1, 5, 6, 7, 8, 7, 5, 2], [1, -400, 2]]
对于字符串,ff = Flipflop.new( ->(x){x.chomp == "BEGIN"}, ->(x){x.chomp == "END"} )
或类似的东西应该有效。
由于你评论并补充说你实际上正在阅读一个文件,我删除了我的旧答案(正如@Stefan所指出的,这无论如何都是错误的(,并对此进行了调整。您可以将其粘贴到文件中并运行它,DATA
IO包含__END__
之后出现的所有内容。在您的应用程序中,您会将其替换为文件。
class Chunker
BEGIN_INDICATOR = "BEGIN"
END_INDICATOR = "END"
def initialize(io)
@io = io
end
def each
return enum_for(:each) if !block_given?
chunk = nil
while !io.eof? do
line = io.readline.chomp
if line == BEGIN_INDICATOR
chunk = []
chunk << line
elsif line == END_INDICATOR
chunk << line
yield chunk.freeze
chunk = nil
elsif chunk
chunk << line
end
end
end
private
attr_reader :io
end
chunker = Chunker.new(DATA)
chunker.each do |chunk|
p chunk
end
# or, thanks to the `return enum_for(:each) if !block_given?` line:
chunker.each.with_index do |chunk, index|
p "at #{index} is #{chunk}"
end
__END__
ignore
BEGIN
some
thing
END
BEGIN
some
other
thing
END
maybe ignore as well
´´´
You could enhance it to throw EOF when `each` is called multiple times or whatever suits your needs.