Reputation: 5399
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
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
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