Split slice, keep delimiters

Hi, I have a problem that would be nicely solved if I could split up a slice and get an iterator over sub-slices, separated by elements that match a certain condition. I.e, exactly like the "split" method on slices, but I need the matching element to be contained in the sub-slices.

More accurately, I don't necessarily need the matching element (the delimiter) to be part of the sub-slices, but I somehow need to connect a particular sub-slice with the preceding delimiter in order to process that sub-slice. Given my original slice, what I ideally would like is something that repeatedly calls a function whose first argument is the delimiter, and the second argument is a slice (or an iterator) containing the following elements up until the next delimiter.

Any ideas how to achieve this nicely? I know I can solve this using nested for loops or similar, but I'm just having fun trying to solve toy problems in the most idiomatic/compact/readable way I can.

Here's an interesting approach: playground, though you need to consider what happens in the last iteration.

You can also create your own iterator: playground.

1 Like

Thanks Alice, I looked at your first suggestion and realised that I forgot to make something clear... The elements of my original slice are enums, and the enum variant I'm splitting on does have an associated data element (i32), i.e:

enum Action {
    BeginShift(u32),
    FallAsleep,
    WakeUp,
}

I want to split with BeginShift as delimiter, and I need to extract it's associated u32 in order to process the following sub-slice. In other words, all delimiters wont be identical, they'll just all be "BeginShift".

I haven't looked at your second suggestion in enough detail yet, but I assume it could be adapted to solve my problem. It would certainly make the "call site" more readable, but since it isn't a standard and documented rust function, I'm not quite sure adding a fair bit of custom iterator code will satisfy the criteria of readability for this particular problem. Still, thanks for the code! I will take a closer look and I'm sure understanding it will help me with other rust problems down the road...

The first solution doesn't assume that the delimiter is identical! The delimiter is stored in the delim variable, and can be accessed inside the loop.

Looking through your iterator example, it's pretty nice and straightforward... Just need to come up with a good name that makes it fairly obvious at the call site that it's splitting into sub-slices while keeping the delimiters.

Also that looks like an advent of code problem :eyes:

Hmmm, but there could be multiple delimiters (i.e multiple BeginShift(u32)) in the slice, all with different numbers attached... I don't see how delim could contain more than one.

In each iteration of the loop it contains the last one seen. Try running it to see the output.

Oh yes, sorry, I see now, the predicate function is updating delim each time it gets called...

Advent of code?? Not sure what that is, I just happen to be stuck in a guarded closet and need to find the best time to escape!

4 Likes