Noel
Noel

Reputation: 5399

Reduce an array of array into a single array with flattening in f#

If I have the following

type Merchant = {
    Id:int;
    OtherItems:int[] }


let (merchant1:Merchant) = {
    Id = 1;
    OtherItems = [| 1; 2 |]}

let (merchant2:Merchant) = {
    Id = 2;
    OtherItems = [| 1; 2 |]}


let merchants = [| merchant1;merchant2|]

And I want to flatten to the following, how do I do it?

Id = 1 OtherItems 1  
Id = 1 OtherItems 2 
Id = 2 OtherItems 1  
Id = 2 OtherItems 2

This is what I have come up with but cant seem to get any further

let x = 
    merchants
     |> Array.map(fun merchant -> merchant, merchant.OtherItems)

Note: I could do the long way in c# oo style but want to use functional way

Upvotes: 3

Views: 509

Answers (2)

Mark Seemann
Mark Seemann

Reputation: 233497

Here's a way using Array.collect:

let x =
    merchants
    |> Array.collect (fun m ->
        m.OtherItems
        |> Array.map (fun x -> { Id = m.Id; OtherItems = [|x|] }))

You could make this easier to understand my first introducing a function that flattens a single merchant:

let flatten merchant = [|
    for x in merchant.OtherItems do
        yield { Id = merchant.Id; OtherItems = [|x|] } |]

This function has the type Merchant -> Merchant [], so it turns a single merchant into an array of merchants, one for each OtherItems.

With that flatten function, you can use the standard, built-in collect function to flatten an array of merchants:

let x' = merchants |> Array.collect flatten

Both options produce this result:

[|
    {Id = 1; OtherItems = [|1|];};
    {Id = 1; OtherItems = [|2|];};
    {Id = 2; OtherItems = [|1|];};
    {Id = 2; OtherItems = [|2|];}
|]

Upvotes: 5

Roman Dibikhin
Roman Dibikhin

Reputation: 856

Use sequence generation:

let mySequence =
    seq {
        for merchant in merchants do
            for otherItem in merchant.OtherItems do
                yield {Id=merchant.Id; OtherItems=[|otherItem|]}
    }

or array generation

let myArray =
    [|
        for merchant in merchants do
            for otherItem in merchant.OtherItems do
                yield {Id=merchant.Id; OtherItems= [|otherItem|]}
    |]

Upvotes: 4

Related Questions