给定像这样的OrderedCollection:
noise1
noise2
noise3
signal1
signal1
signal1
signal1
randomButInteresting
noise4
noise5
我想选择一个新的OrderedCollection所有对象“signal1”和该系列“signal1”之后出现的对象,“randomButInteresting”。 (每个Collection只会发生一次同一个信号。)
最优雅的方法是什么?
答案 0 :(得分:5)
直接方法类似于
| data result lastWasSignal |
data := #( #noise1 #noise2 #noise3 #signal1 #signal1 #signal1 #signal1 #randomButInteresting #noise4 #noise5 ).
lastWasSignal := false.
result := data select: [ :value |
| isElementAppropriate |
isElementAppropriate := value = #signal1 or: [ lastWasSignal ].
lastWasSignal := value = #signal1.
isElementAppropriate
].
result
是O(n)。更聪明的是找到信号组的边界,使用二进制搜索只发生一次。
答案 1 :(得分:2)
您可以使用PetitParser,因为您基本匹配输入流上的特定模式。为清楚起见,添加了一些注释的解析器定义如下:
" the parser that accepts the symbol #signal1 "
signal := PPPredicateObjectParser expect: #signal1.
" the parser that accepts the symbol #signal1 not followed by something else "
pattern := signal , signal negate.
" the parser that extract the second symbol "
parser := pattern map: [ :signal :random | random ].
当您在输入数据上运行时,您会得到:
data := #(noise1 noise2 noise3 signal1 signal1
signal1 signal1 randomButInteresting
noise4 noise5).
parser matchesIn: data -> #(randomButInteresting)
答案 2 :(得分:2)
在PetitParser中使用Lukas版本,但在结果中保留所有'signal1':
" the parser that accepts the symbol #signal1 "
signal := PPPredicateObjectParser expect: #signal1.
" the parser that accepts many symbols #signal1 followed by something else "
pattern := signal plus , signal negate.
data := #(noise1 noise2 noise3 signal1 signal1 signal1 signal1 randomButInteresting noise4 noise5).
pattern flatten matchesSkipIn: data -> an OrderedCollection(#(#signal1 #signal1 #signal1 #signal1 #randomButInteresting))
答案 3 :(得分:1)
使用输入和输出流的不同解决方案(是的,我喜欢流: - )):
data := #(noise1 noise2 noise3 signal1 signal1 signal1 signal1 randomButInteresting noise4 noise5).
"Let's create an OrderedCollection from an output stream"
OrderedCollection streamContents: [:output |
|datast|
"We are basically streaming on the input data, so let's use a stream:"
datast := data readStream.
"We ignore everything before #signal1"
datast skipTo: #signal1.
"We add the #signal1we just found"
output nextPut: #signal1.
"And we add all the subsequent #signal1"
[datast peek = #signal1]
whileTrue: [output nextPut: datast next].
"Finally we add the element after the last #signal1"
output nextPut: datast next
]