Jeff_hk
Jeff_hk

Reputation: 421

F# and Series, How to write a Series.choose?

I have decided to write a Series.choose function, similar to the one we have on Seq and I wanted to know if you think it is the best way to write it, going back to a Seq as there is a function there.

let choose (f: 'K * 'V -> ('K * 'U) option) (e : Series<'K,'V>) =
        e |> Series.map (fun k v -> k, v)
          |> Series.values
          |> (Seq.choose f)
          |> Series.ofValues
          |> Series.map (fun _ v -> snd v)
          |> Series.indexWith (e |> Series.keys)

Thanks

Upvotes: 1

Views: 135

Answers (2)

Jeff_hk
Jeff_hk

Reputation: 421

Here what I wrote for my "Toolbox". Just in case it saves time to someone in the future...

    /// Choose only on values keeping the same keys
    let chooseV (f: 'V -> 'U option) (e : Series<'K,'V>) =
        e |> Series.mapAll (fun _ (Some v) -> f v)
          |> Series.dropMissing

    /// Choose on both keys and values, changing the keys to type 'J
    let chooseKV (f: 'K * 'V -> ('J * 'U) option) (e : Series<'K,'V>) =
        e |> Series.mapAll (fun k (Some v) -> f (k, v))
          |> Series.dropMissing
          |> fun e1 -> e1.SelectKeys (fun kvp -> fst kvp.Value.Value)
          |> Series.mapValues snd

    /// Choose on just the values using the keys in the function
    let choose (f: 'K * 'V -> ('K * 'U) option) (e : Series<'K,'V>) =
        e |> Series.mapAll (fun k (Some v) -> f (k, v))
          |> Series.dropMissing
          |> Series.mapValues snd 

Upvotes: 0

Alexey Romanov
Alexey Romanov

Reputation: 170839

mapAll is nearly what you need, it just has a slightly different signature (and in particular, can't change the keys). If you do need to change the keys, it becomes more difficult but still shouldn't require going via Seq. It also depends on how you want to deal with missing values in e.

Untested (because I don't have Visual Studio here), and assumes e has no missing values, but should give the idea:

let choose (f: 'K * 'V -> ('K * 'U) option) (e : Series<'K,'V>) =
    e |> Series.mapAll (fun k (Some v) -> f (k, v)) // Series<'K, ('K, 'U)> 
      |> Series.dropMissing // drops cases where f returned None
      |> fun e1 -> e1.SelectKeys (fun kvp -> fst kvp.Value.Value) // changes the keys to the ones f returned
      |> Series.mapValues snd // removes the keys from the values

Upvotes: 3

Related Questions