首页 > 解决方案 > Ruby:在字符串之上构建令牌生成器

问题描述

我想创建一个可以在 String 和 Regex 上实例化的类(它描述了如何标记字符串),并提供了一个方法next_token,它分别返回与 regex 匹配的字符串的下一部分,方式String#scan是在职的。例如,如果我做一个

t = Tokenizer.new('abcdefgh', /.../)
a = t.next_token
b = t.next_token
c = t.next_token

应该设置a'abc'bto'def'cto nil。这是一个明显而简单的解决方案:

class Tokenizer
  def initialize(str, reg)
     @tokenized_str = str.scan(reg)
     @next_ind = 0
  end
  def next_token
     @tokenized_str[@next_ind].tap { @next_ind += 1 }
  end
end

此解决方案要求在构造函数中将整个字符串拆分为一个数组。我想实现一种“惰性”方法,仅在next_token发出调用时计算下一个令牌。有人可以建议怎么做吗?实际上,String#scan必须已经内置了这样的生成器,因为我们可以用块调用它,但我不知道如何在我的情况下使用它。

我想知道这是否是使用 a 的好方法Fiber,因为我在这里所做的闻起来像协同例程,但对于这类问题,也许有更简单的解决方案。性能也将是一个问题,因为我的应用程序将大量使用Tokenizer该类。

标签: regexrubystring

解决方案


您可以使用StringScanner#scan_until然后删除与模式匹配的部分String#splitor String#gsub

ss = StringScanner.new('a-b-c-d-e-f-g')
#=> #<StringScanner 0/13 @ "a-b-c...">
while s = ss.scan_until(/-/)
   puts s.gsub(/-/, '') # or s.split(/-/)
end  
#a
#b
#c
#d
#e
#f
#=> nil

推荐阅读