I usually tackle this by breaking it down into pseudocode that describe successive steps of the process, then replacing those with local variables that handle that step (and abstract the functionality behind that variable, which helps in dev and debugging etc).
Here goes my quick "first pass":
- take the initial array and pass the IDs through my "distinct" helper rule to get a list of unique IDs ("distinct" is usually just an expression rule that calls union() on the input rule input, repeated)
- iterate over that list of IDs and get lists of indexes of the index locations in the initial dictionary for the current id ("wherecontains()")
- (can possibly be done at the same moment as step 2) - narrow down to just the first index for each item
- call index() on the original dictionary array, passing in the narrowed-down index values, to produce the initial list entries for each ID
Edit: merely for the sake of curiosity, I timed myself at 3 minutes, 4 seconds to translate the above steps into code and whip up this:
a!localVariables(
local!initialDict: {
{output: "OK", id: "abcd", description: "hello"},
{output: "OK", id: "abcd", description: "hi"},
{output: "OK", id: "yxz", description: "bye"},
{output: "OK", id: "yxz", description:"goodnight"},
{output: "OK", id: "opt", description: "ok"}
},
local!uniqueIds: rule!RULE_General_distinct(array: local!initialDict.id), /* just does a "union()" on ri!array, on itself, quickly eliminating duplicates */
local!indices: a!forEach(
local!uniqueIds,
index(
wherecontains(fv!item, touniformstring(local!initialDict.id)),
1,
{}
)
),
index(
local!initialDict,
local!indices
)
)
