Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Remove a single non-unique value from a sequence in F#

Tags:

f#

I have a sequence of integers representing dice in F#.

In the game in question, the player has a pool of dice and can choose to play one (governed by certain rules) and keep the rest.

If, for example, a player rolls a 6, 6 and a 4 and decides to play one the sixes, is there a simple way to return a sequence with only one 6 removed?

Seq.filter (fun x -> x != 6) dice

removes all of the sixes, not just one.

like image 395
mavnn Avatar asked Dec 05 '25 21:12

mavnn


2 Answers

Non-trivial operations on sequences are painful to work with, since they don't support pattern matching. I think the simplest solution is as follows:

let filterFirst f s =
    seq {
        let filtered = ref false
        for a in s do
            if filtered.Value = false && f a then
                filtered := true
            else yield a
    }

So long as the mutable implementation is hidden from the client, it's still functional style ;)

like image 125
Juliet Avatar answered Dec 08 '25 22:12

Juliet


If you're going to store data I would use ResizeArray instead of a Sequence. It has a wealth of functions built in such as the function you asked about. It's simply called Remove. Note: ResizeArray is an abbreviation for the CLI type List.

let test = seq [1; 2; 6; 6; 1; 0]
let a = new ResizeArray<int>(test)
a.Remove 6 |> ignore
Seq.toList a |> printf "%A"

// output
> [1; 2; 6; 1; 0]

Other data type options could be Array

let removeOneFromArray v a =
    let i = Array.findIndex ((=)v) a
    Array.append a.[..(i-1)] a.[(i+1)..]

or List

let removeOneFromList v l = 
    let rec remove acc = function
        | x::xs when x = v -> List.rev acc @ xs
        | x::xs -> remove (x::acc) xs
        | [] -> acc
    remove [] l
like image 40
gradbot Avatar answered Dec 08 '25 23:12

gradbot



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!