在Ruby中提取2个数字之间的项



问题:

  • 给定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所指出的,这无论如何都是错误的(,并对此进行了调整。您可以将其粘贴到文件中并运行它,DATAIO包含__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.

相关内容

  • 没有找到相关文章

最新更新