String 以Rebol或Red格式搜索字符串
我对搜索大量长字符串感兴趣,尝试在rebol中创建一个类似sed的实用程序作为学习练习。作为第一步,我决定搜索一个角色:String 以Rebol或Red格式搜索字符串,string,rebol,rebol2,red,String,Rebol,Rebol2,Red,我对搜索大量长字符串感兴趣,尝试在rebol中创建一个类似sed的实用程序作为学习练习。作为第一步,我决定搜索一个角色: >> STR: "abcdefghijklmopqrz" >> pos: index? find STR "z" == 18 >> pos == 18 太好了!让我们找点别的 >> pos: index? find STR "n" ** Script Error: index? expected series argume
>> STR: "abcdefghijklmopqrz"
>> pos: index? find STR "z"
== 18
>> pos
== 18
太好了!让我们找点别的
>> pos: index? find STR "n"
** Script Error: index? expected series argument of type: series port
** Where: halt-view
** Near: pos: index? find STR "n"
>> pos
== 18
什么-(
是的,我搜索的字符串中没有“n”。但是解释器爆炸而不是做一些合理的事情,比如在pos中返回一个可测试的“null”字符有什么好处呢
我被告知我应该这样做:
>> if found? find STR "z" [pos: index? find STR "z"]
== 18
>> if found? find STR "n" [pos: index? find STR "n"]
== none
>> pos
== 18
>> if found? find STR "z" [pos: index? find STR "z"]
== 18
>> if found? find STR "n" [pos: index? find STR "n"]
== none
>> pos
== 18
真的吗?我必须搜索字符串两次;第一次只是为了确保再次搜索“安全”
所以我有一个三部分的问题:
>> if found? find STR "z" [pos: index? find STR "z"]
== 18
>> if found? find STR "n" [pos: index? find STR "n"]
== none
>> pos
== 18
>> if found? find STR "z" [pos: index? find STR "z"]
== 18
>> if found? find STR "n" [pos: index? find STR "n"]
== none
>> pos
== 18
真的吗?我必须搜索字符串两次;第一次只是为了确保再次搜索“安全”
当然,您不必搜索字符串两次。但是索引?
(可能是将来的名称,因为它不返回yes/no:索引的)在给定NONE!输入时不会返回NONE!值。它假定调用者想要返回整数位置,如果不能返回,则会引发错误
向导如何实现我的搜索功能?
要消除双重搜索,可以使用短路评估
>> all [pos: find STR "z" pos: index? pos]
== 18
>> pos
== 18
>> all [pos: find STR "n" pos: index? pos]
== none
>> pos
== none
但请注意,如果不引入第二个变量,您将覆盖以前的pos
。假设您调用变量index
,而pos是临时变量:
>> all [pos: find STR "z" index: index? pos]
== 18
>> index
== 18
>> all [pos: find STR "n" index: index? pos]
== none
>> index
== 18
在表达式中间的任意点抛出集合词的能力非常强大,这就是为什么像多重初始化(a:b:c:0
)这样的东西不是语言的特殊功能,而是不属于计算器模型的东西
瑞德会改变这一切吗?
index?
(coughindex of
)返回一个NONE!值(如果给定一个NONE!输入)的好处不太可能超过它如此宽容所带来的问题。这始终是一种平衡
请注意,FIND的行为确实如您所期望的那样。FIND?只是一种语法上的便利,它可以将找到的位置转换为真值,将NONE!转换为假值。它相当于调用true?(但在阅读时只需要稍微熟练一点).没有必要在“如果”或“除非”或“任一”的情况下使用它,因为他们会将“无”结果视为“假”,而将任何位置视为“真”
一旦我有了一个有效的索引,最有效的CPU替换方法是什么?
最快的可能是挂在位置上,说change pos#“x”
(尽管是内部的“位置”)是通过索引加序列实现的,而不是独立的指针。因此,在微优化世界中,优势并不是那么显著,在微优化世界中,我们计算的是偏移量的增加……)
至于使用索引的操作:我会说选择您最喜欢的方式,然后进行微优化
我个人并不认为STR/:index:#“x”
看起来那么好,但它是最简洁的字符
STR/(index):#“x”
做了同样的事情,在我看来看起来更好。但代价是源代码结构有点膨胀。这是一个SET-PATH!系列,包含一个PAREN!系列,后跟一个CHAR!…所有这些都嵌入到保存代码的原始系列“vector”中。在引擎盖下会出现局部性问题
看起来很幼稚的POKE可能是最快的。POKE STR index#“x”
。它可能看起来像“4个元素而不是2个”,但路径案例中的“2个元素”只是一种幻觉
在Rebol中,猜测总是有点困难,因此您必须收集数据。您可以运行一些重复的迭代测试来找出答案。要对代码块计时,请参阅内置的delta time
红色的编译表单应该是等效的,但如果以某种方式结束了对它的解释,您可能会有与Rebol类似的时间安排。毫不奇怪,HostileFork答案完美地涵盖了所有内容!+1
我只是想为我经常使用的第1点添加一个替代解决方案:
>> attempt [index? find STR "z"]
== 18
>> attempt [index? find STR "n"]
== none
Rebol 2和Rebol 3的在线文档以红色/Rebol搜索字符串非常简单方便。关于您遇到的问题,让我为您解包详细信息:
首先,解释器以错误消息的形式向您提供了一个很好的错误提示:index?类型为:series port
的预期系列参数。这意味着您在错误的数据类型上使用了index?
。这是怎么发生的?原因很简单,因为函数在电子搜索失败:
>> str: "abcdefghijklmopqrz"
>> find str "o"
== "pqrz"
>> type? find str "o"
== string!
>> find str "n"
== none
>> type? find str "n"
== none!
因此,直接对find
的结果使用index?
是不安全的,除非您知道搜索不会失败。如果您仍然需要提取索引信息,安全的方法是首先测试find
的结果:
>> all [pos: find str "o" index? pos]
== 14
>> all [pos: find str "n" index? pos]
== none
>> if pos: find str "o" [print index? pos]
== 14
>> print either pos: find str "n" [index? pos][-1]
== -1
根据您的需要,这些只是实现它的安全方法的示例。请注意,none
在if
或中的条件测试中充当false
,因此在这种情况下使用found?
是多余的
现在让我们来解释一下给你们带来困惑的核心问题。
Rebol语言有一个基本概念,称为
>> a: next s
== "ello"
>> b: skip s 3
== "lo"
>> s: at s 5
== "o"
>> reduce [a b s]
== ["ello" "lo" "o"]
>> reduce [index? a index? b index? s]
== [2 4 5]
>> STR: "abcdefghijklmopqrz"
>> find STR "z"
== "z"
>> find STR "n"
== none
>> pos: find STR "o"
>> if pos [print "found"]
found
>> print ["sub-string from `o`:" pos]
sub-string from `o`: opqrz
>> length? pos
== 5
>> index? pos
== 14
>> back pos
== "mopqrz"
>> skip pos 4
== "z"
>> pos: find STR "n"
>> print either pos ["found"]["not found"]
not found
>> print either pos [index? pos][-1]
-1
>> s: "The score is 1:2 after 5 minutes"
>> if pos: find/tail s "score is " [print copy/part pos find pos " "]
1:2