Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What is the most elegant way to select the following items from an OrderedCollection:

Given an OrderedCollection like this:

noise1
noise2
noise3
signal1
signal1
signal1
signal1
randomButInteresting
noise4
noise5

i want to select to a new OrderedCollection all the objects "signal1" and the object that comes after this series of "signal1"s, "randomButInteresting". (a series of one and the same signal occurs only once per Collection.)

What is the most elegant way to do this?

like image 697
Helene Bilbo Avatar asked Aug 05 '12 14:08

Helene Bilbo


2 Answers

The straight method is something like

| 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

It's O(n). More clever would be to find bounds of signal group, which occurs only once, using binary search.

like image 64
Mekanik Avatar answered Oct 21 '22 03:10

Mekanik


Using Lukas' version with PetitParser, but keeping all the 'signal1' in the result:

" 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))
like image 25
Damien Cassou Avatar answered Oct 21 '22 01:10

Damien Cassou