algorithm - Filter an array or list by consecutive pairs based on a matching rule -
this trivial, , have solution i'm not happy it. somehow, (much) simpler forms don't seem work , gets messy around corner cases (either first, or last matching pairs in row).
to keep simple, let's define matching rule any 2 or more numbers have difference of two. example:
> filtertwins [1; 2; 4; 6; 8; 10; 15; 17]
val : int list = [2; 4; 6; 8; 10; 15; 17]
the code use this, feels sloppy , overweight:
let filtertwins list = let func item acc = let previtem, resultlist = acc match previtem, resultlist | 0, [] -> item, [] | var, [] when var - 2 = item -> item, item::var::resultlist | var, hd::tl when var - 2 = item && hd <> var -> item, item::var::resultlist | var, _ when var - 2 = item -> item, item::resultlist | _ -> item, resultlist list.foldback func list (0, []) |> snd
i intended own original exercise experiment list.foldback
, large lists , parallel programming (which went well) ended messing "easy" part...
guide through answers
- daniel's last, 113 characters*, easy follow, slow
- kvb's 2nd, 106 characters* (if include function), easy, return value requires work
- stephen's 2nd, 397 characters*, long winded , comparably complex, fastest
- abel's, 155 characters*, based on daniel's, allows duplicates (this wasn't necessity, btw) , relatively fast.
there more answers, above distinct, believe. hope didn't hurt anybody's feelings accepting daniel's answer solution: each , every 1 solution deserves selected answer(!).
* counting done function names 1 character
would want?
let filtertwins l = let rec filter l acc flag = match l | [] -> list.rev acc | :: b :: rest when b - 2 = -> filter (b::rest) (if flag b::acc else b::a::acc) true | _ :: t -> filter t acc false filter l [] false
this terribly inefficient, here's approach using more built-in functions:
let filtertwinssimple l = l |> seq.pairwise |> seq.filter (fun (a, b) -> b - 2 = a) |> seq.collect (fun (a, b) -> [a; b]) |> seq.distinct |> seq.tolist
maybe better:
let filtertwinssimple l = seq { (a, b) in seq.pairwise l if b - 2 = yield yield b } |> seq.distinct |> seq.tolist
Comments
Post a Comment