sircodesalot
sircodesalot

Reputation: 11439

How do you flatten a set while keeping the parent object?

In C# you would just use SelectMany which has an overload for holding onto the parent object. How do you do the same thing in F#? That is, I want to iterate over a set of assemblies and return all of those assemblies that have classes implementing a specific attribute.

I know I collect is similar to select many, but I'm not sure how to use it while maintaining the parent (assembly) information.

Upvotes: 0

Views: 334

Answers (2)

Tomas Petricek
Tomas Petricek

Reputation: 243106

You can implement SelectMany using collect by applying a map to the collection of "children" that you want to return for each element of the "parent" collection:

Assuming you have some source and want to get children using getChildren (for each element in source) and then you want to calculate the result using selectResult that takes both child and parent, you can write the following using SelectMany:

source.SelectMany
  ( (fun parent -> getChildren parent),
    (fun parent child -> selectResult parent child ) )

Using collect, the same code looks as follows (note that the map operation is applied inside the lambda function that we're passing to collect - where parent is still in scope):

source |> Seq.collect (fun parent ->
  getChildren parent 
  |> Seq.map (fun child ->
      selectResult parent child ))  

It is also worth noting that the behavior captured by SelectMany can be implemented - perhaps in a more readable way - using F# sequence expressions like this:

seq { for parent in source do 
        for child in getChildren parent do
          yield selectResult parent child }

Upvotes: 1

Lee
Lee

Reputation: 144206

It looks like you just need filter instead of collect:

let hasTypeWithAttribute<'t when 't :> Attribute> (a: Assembly) = a.GetTypes() |> Array.exists (fun t -> t.GetCustomAttributes(typeof<'t>, true).Length > 0)

let assemblies = inputSet |> Set.filter hasTypeWithAttribute<AttributeName>

Upvotes: 1

Related Questions