\$\begingroup\$
\$\endgroup\$
4
This takes a list of categories and organizes them into a tree-type structure based on their parentId
. This code works, but is obviously a little over-complicated. How can I optimize it?
type ValidString = | ValidString of string | NotValid
type CategoryStructure = {
Id: ValidString;
ParentId: ValidString;
Name: ValidString;
Abbreviation: ValidString;
Description: ValidString;
SapId: ValidString;
Section: ValidString;
SectionPosition: ValidString
}
type DynamicCategories = {
Category: CategoryStructure;
SubCategories: seq<DynamicCategories>
}
let rec private structureCategories (fullList: CategoryStructure list)
(list: CategoryStructure list) =
List.fold (fun acc elem ->
// get all categories and details
let categories = fullList
let mainAcc =
[
for row in categories do
if row = elem
then
let subs =
List.fold (fun acc' elem' ->
if row.Id = elem'.ParentStructureId
then
let modifiedList = elem' :: List.empty<CategoryStructure>
let foundSubCategory =
{
Category = elem';
SubCategories = structureCategories fullList modifiedList |> Seq.ofList
}
foundSubCategory :: acc'
else acc'
) List.empty<DynamicCategories> categories
|> Seq.ofList
yield{
Category = elem;
SubCategories = subs
}
]
mainAcc @ acc
) List.empty<DynamicCategories> list
// get the initial parent categories and then call the above code to finish the organizing the list
let getStructuredCategories () =
let categories = allCategoriesAndDetails () |> List.ofSeq
[
for row in categories do
if row.ParentStructureId = NotValid
then yield row
] |> structureCategories categories |> Seq.ofList
Jamal
35.2k13 gold badges134 silver badges238 bronze badges
asked Oct 8, 2015 at 6:04
1 Answer 1
\$\begingroup\$
\$\endgroup\$
2
Here is an optimized version that I have discovered:
let getStructuredCategories () =
let fullList = allCategoriesAndDetails ()
let parentList () =
allCategoriesAndDetails ()
|> Seq.filter (fun p -> p.ParentStructureId = NotValid)
let rec toTree (fullList': seq<CategoryStructure>) (parent: CategoryStructure) =
fullList'
|> Seq.filter (fun x -> x.ParentStructureId = parent.Id)
|> Seq.map (fun x ->
{
Category = x;
SubCategories =
toTree fullList' x
})
seq {
for row in parentList () do
yield {
Category = row;
SubCategories = toTree fullList row
}
}
Can someone else do better?
answered Oct 9, 2015 at 2:56
-
\$\begingroup\$ The last
seq
can be replaced withparentList() |> Seq.map (fun t -> Category=t;SubCategories=toTree fillList row
\$\endgroup\$John Palmer– John Palmer2015年10月09日 03:30:17 +00:00Commented Oct 9, 2015 at 3:30 -
\$\begingroup\$
filter |> map
can be replaced bychoose
\$\endgroup\$John Palmer– John Palmer2015年10月09日 03:30:38 +00:00Commented Oct 9, 2015 at 3:30
lang-ml
Seq.fold
instead ofList.fold |> Seq.ofList?
\$\endgroup\$let ...() = let t = allcateogriesanddetails(); t |> List.Filter (fun t -> t.ParentStructureID=NotValid) |> StructureCategories categories
\$\endgroup\$