5

给定这样的 OrderedCollection:

noise1
noise2
noise3
signal1
signal1
signal1
signal1
randomButInteresting
noise4
noise5

我想为新的 OrderedCollection 选择所有对象“signal1”以及这一系列“signal1”之后的对象,“randomButInteresting”。(一系列相同的信号在每个 Collection 中只出现一次。)

最优雅的方法是什么?

4

4 回答 4

6

直接的方法类似于

| 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)。更聪明的方法是使用二分搜索找到仅出现一次的信号组的边界。

于 2012-08-05T15:09:11.523 回答
3

使用带有 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))
于 2012-08-05T17:58:13.173 回答
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)
于 2012-08-05T17:27:29.547 回答
2

使用输入和输出流的不同解决方案(是的,我喜欢流:-)):

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
    ]
于 2012-08-05T17:45:12.487 回答