在Ruby中提取两个数字之间的项
问题:在Ruby中提取两个数字之间的项,ruby,algorithm,Ruby,Algorithm,问题: 给定Ruby中的数字数组,返回出现在1和2之间的数字组 数字1和2不会出现在其他1和2之间(不存在子集的子集) 示例1 输入:[1,3,2,1,4,2] 输出:[[1,3,2],[1,4,2]] 示例2 输入:[0,1,3,2,10,1,5,6,7,8,7,5,2,3,1,-400,2,12,16] 输出:[[1,3,2],[1,5,6,7,8,7,5,2],[1,-400,2]] 我的直觉是使用#chunk和#drop_的组合,而或生成器 提前谢谢。听起来像是一个面试问题。我将解释
- 给定Ruby中的数字数组,返回出现在1和2之间的数字组
- 数字1和2不会出现在其他1和2之间(不存在子集的子集)
[1,3,2,1,4,2]
输出:[[1,3,2],[1,4,2]]
示例2
输入:[0,1,3,2,10,1,5,6,7,8,7,5,2,3,1,-400,2,12,16]
输出:[[1,3,2],[1,5,6,7,8,7,5,2],[1,-400,2]]
我的直觉是使用#chunk
和#drop_的组合,而或生成器
提前谢谢。听起来像是一个面试问题。我将解释我能想到的最简单的算法:
在数组中循环一次,并在运行时生成输出。当您遇到1
时,您将其和随后的数字存储到另一个临时数组中。当遇到2
时,将数组放入输出数组中。边缘情况包括:
- 另一个
1
在您开始构建临时阵列之后
- 如果没有临时数组,则为
2
第一种情况很简单,当遇到1
时,请始终构建一个新的临时数组。对于第二个,您必须检查临时数组中是否有任何项,如果临时数组不是空的,则只将临时数组附加到输出中
这应该可以让你开始了。你可以使用和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]
由于您评论并添加了您实际上正在阅读一个文件,我删除了我的旧答案(正如@Stefan所指出的,这个答案无论如何都是错误的),然后用这个来补充。您可以将其粘贴到一个文件中并运行它,数据
IO包含\uuuuu END\uuuu
之后显示的所有内容。在应用程序中,您可以将其替换为您的文件
类Chunker
开始指示灯=“开始”
END_INDICATOR=“END”
def初始化(io)
@io=io
结束
定义每个
返回(:每个)的枚举u如果!给你块钱?
chunk=nil
虽然io.eof?做
line=io.readline.chomp
如果行==开始指示器
区块=[]
chunk适用于所有想在海滩上散步的人,但由于明显的原因不能:
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”})
或类似的东西应该可以使用。这是一个使用[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'
使用可枚举的#每个_和_对象
,如果使用其他
,为什么不使用好的旧:
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
tmp=[]
拾取=错误
输入。每个带有_对象([])的| e,res|
如果e==开始
皮卡=真
这听起来像是家庭作业。到目前为止你试过什么?展示你的代码。嗨,这不是为了学术目的。我有一个4 GB的日志文件,其中的行由我需要提取出来的单词BEGIN
和END
包围。这是我的第一次尝试。我更喜欢使用惰性枚举的解决方案。谢谢你。这个问题不是程序面试的问题。我同时喜欢和不喜欢这个解决方案。因为人字拖:-)@Pascal是的,人字拖很奇怪。但令人惊讶的是,很难找到一个几乎同样简洁的替代品。