Home > Uncategorized > Seq.split in F#

Seq.split in F#

I wanted to split a list into sub-lists given some kind of separator. For example, I wanted:

[1;4;5;0;0;7;9;1;0;3;0;0;0;9] to be split by the zero markers into [[1;4;5];[7;9;1];[3];[9]]

I could not find anything in the standard F# libraries. I found this snippet:

let split (selector:’a->bool) (source:seq<’a>) :seq<seq<’a>>=
  let i = ref 0
  source
  |> Seq.groupBy (fun elem -> if selector elem then incr i
                              !i)
  |> Seq.map snd

which is interesting but it produces (ignoring the difference between seq and list):

[[1;4;5];[0];[0;7;9;1];[0;3];[0];[0];[0;9]]

which was not exactly what I wanted. Like regex split i did not want to keep the split symbols. Also I think groupBy adds unnecessary performance overhead.

After a bit of fiddling I came up with this:

let split (pred : ‘a -> bool) (source : seq<’a>) : seq<list<’a>> =
    seq {
        let cur = ref (new List<_>())
        for elem in source do
            if pred elem then
                if cur.Value.Count > 0 then
                    yield Seq.toList(cur.Value)
                    cur.Value.Clear()
            else
                cur.Value.Add(elem)
    }

Are there better ways? Clearer? With better performance? More functional in style?

About these ads
Categories: Uncategorized
  1. No comments yet.
  1. No trackbacks yet.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

Follow

Get every new post delivered to your Inbox.

%d bloggers like this: