似乎Smalltalk实现缺少一种算法,该算法返回String中子字符串的所有索引。最相似的元素仅返回元素的一个索引,例如:firstIndexesOf:in:,findSubstring:,findAnySubstring:variant。
有implementations in Ruby,但是第一个依靠Ruby hack,第二个不能忽略重叠的Strings,最后一个使用Enumerator类,我不知道如何将其转换为Smalltalk。我不知道这Python implementation是否是开始的最佳途径,因为考虑了两种情况(是否重叠)并且不使用正则表达式。
我的目标是找到提供以下行为的程序包或方法:
'ABDCDEFBDAC' indicesOf: 'BD'. "#(2 8)"
考虑重叠时:
'nnnn' indicesOf: 'nn' overlapping: true. "#(0 2)"
不考虑重叠时:
'nnnn' indicesOf 'nn' overlapping: false. "#(0 1 2)"
在Pharo中,当在Playground中选择了文本时,扫描仪会检测到该子字符串并突出显示匹配项。但是我找不到这个的String实现。
到目前为止,我的最大努力是在String(Pharo 6)中实现了该实现:
indicesOfSubstring: subString
| indices i |
indices := OrderedCollection new: self size.
i := 0.
[ (i := self findString: subString startingAt: i + 1) > 0 ] whileTrue: [
indices addLast: i ].
^ indices
答案 0 :(得分:5)
首先让我澄清一下,Smalltalk集合是基于1的,而不是基于0的。因此,您的示例应阅读
'nnnn' indexesOf: 'nn' overlapping: false. "#(1 3)"
'nnnn' indexesOf: 'nn' overlapping: true. "#(1 2 3)"
请注意,我也注意到了@lurker的观察(并且也对选择器进行了调整)。
现在,从您的代码开始,我将对其进行如下更改:
indexesOfSubstring: subString overlapping: aBoolean
| n indexes i |
n := subString size.
indexes := OrderedCollection new. "removed the size"
i := 1. "1-based"
[
i := self findString: subString startingAt: i. "split condition"
i > 0]
whileTrue: [
indexes add: i. "add: = addLast:"
i := aBoolean ifTrue: [i + 1] ifFalse: [i + n]]. "new!"
^indexes
请确保您编写了一些单元测试(不要忘了练习边框案例!)
答案 1 :(得分:1)
已编辑
如果您能在“更大的前景”中告诉我们您需要实现什么,那也很好。有时候Smalltalk提供了不同的方法。
Leandro在代码上击败了我(他的代码效率更高),但是我已经写了它,所以我也将分享它。听取他关于Smalltalk是基于1的=>重写示例的建议。
我以Smalltalk / X和Pharo 6.1为例。
代码为:
indexesOfSubstring: substringToFind overlapping: aBoolean
| substringPositions aPosition currentPosition |
substringPositions := OrderedSet new. "with overlap on you could get multiple same
positions in the result when there is more to find in the source string"
substringToFindSize := substringToFind size. "speed up for large strings"
aPosition := 1.
[ self size > aPosition ] whileTrue: [
currentPosition := self findString: substringToFind startingAt: aPosition.
(currentPosition = 0) ifTrue: [ aPosition := self size + 1 ] "ends the loop substringToFind is not found"
ifFalse: [
substringPositions add: currentPosition.
aBoolean ifTrue: [ aPosition := aPosition + 1 ] "overlapping is on"
ifFalse: [ aPosition := currentPosition + substringToFindSize ] "overlapping is off"
]
].
^ substringPositions
我已解决一些发生在我身上的问题。不要忘了尽可能多地测试它!