regex - 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'
和b
to'def'
和c
to 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
该类。
解决方案
您可以使用StringScanner#scan_until
然后删除与模式匹配的部分String#split
or 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
推荐阅读
- java - 如何使用扫描仪将写入器与用户输入一起使用
- connection - 以编程方式更新 Airflow 中的连接时出现问题
- java - 当我在 arrayList 中使用 .get() 方法打印对象时,如何防止打印哈希码?
- php - 在 laravel 中使用 GuzzleHttp 发送原始空 json
- express - 子文档 mongoose 返回 [object]
- firebase - 同时运行两个功能项目
- java - 3d 迷宫的数组索引超出范围
- mysql - 如何对 MySQL 中的行进行唯一编号?
- python-3.x - 它不会在 csv 文件中保存任何内容?
- visual-studio-code - 如何重置 VS Code 中的默认浏览器设置?