5

次のような OrderedCollection を指定します。

noise1
noise2
noise3
signal1
signal1
signal1
signal1
randomButInteresting
noise4
noise5

すべてのオブジェクト「signal1」と、この一連の「signal1」の後に続くオブジェクト「randomButInteresting」を新しい OrderedCollection に選択したいと考えています。(一連の同じ信号は、コレクションごとに 1 回だけ発生します。)

これを行う最もエレガントな方法は何ですか?

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

Lukas のバージョンを PetitParser で使用しますが、結果にすべての '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

入力ストリームと出力ストリームを使用する別のソリューション(はい、私はストリームが好きです:-)):

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 に答える
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 に答える