Array Aggregate - HiStructClient/femcad-doc GitHub Wiki

Aggregate

Aggregate can be used following way

Input

indices := [1,2,3],[4,5,6],[7,8,9](/HiStructClient/femcad-doc/wiki/1,2,3],[4,5,6],[7,8,9)
joinList := indices.Aggregate([],a,b=>a+b)
print joinList 

Output

[1,2,3,4,5,6,7,8,9]

Mind the brackets

#pokud je v prvním argumentu výraz, tak Aggregate funguje i bez závorek...
A  := [1,2,3].Aggregate( 2 * [1,2] * 2, a, b => a + [b*200]) 
# nebo i
A1 := [1,2,3].Aggregate( [], a, b => a + [b*200]) 

# pokud je prvním argumentem odkaz na proměnnou, dojde bez závorek k chybě...
Ca := [1,2]
C  := [1,2,3].Aggregate( Ca, a, b => a + [b*200] )  # error

# se závorkami funguje...
Ba := [1,2]
B  := [1,2,3].Aggregate(Ba, ( a, b => a + [b*200] ) )

Using updater in aggregated part

While using an updater in Aggregate, keep in mind a difference between eager and lazy evaluation.

Using the := sign (lazy) will force the aggregate to store and keep all the iterations, which might cause speed and memory issues. Much more favourable is to use = sign (eager eval.), aggregate gets updated in every iteration with already calculated values:

.Aggregate( arr, a,b => a{ Quantity = a.Quantity + b.Quantity }

Using of values from previous iterations

Aggregate is the right tool for more complex iterations - it allows to store data from previous iterations and use them in current iteration (this is where Select fails since we cannot expand arrays in runtime).

A good example is iterative design of sections on a frame:

In first iteration, startingSections are assigned. In every other iteration a function updateSectionsFn(oldSections) is used. The function checks, whether all the checks of sections are ok, if yes, an empty array is returned, if not, a new set of sections is returned.

Design loop checks in every iteration whether there has already been added an empty array, in which case another empty arrays are being added until the last iteration.

designSectionsLoop := res.f.EnumerableRange(maxIterations).Aggregate( [],a,b =>
   a + ((b == 0)                            # In first iteration, assign default sections
         ?([startingSections])             
         :( ((b-1) >= a.Count) )            # Has the design loop been already stopped?
            ?([])                                # If yes, add another empty cell,
            :(updateSectionsFn( a[b-1] )         # if not, design section from analysis based on last iteration
         ) 
      )
   )