Skip to main content
chiarag0001
October 16, 2024
Solved

Save first occurence from an array of elements

  • October 16, 2024
  • 3 replies
  • 0 views

Hello, I need to create rule that takes an array of dictionaries in input and if multiple of these elements have the same "id" value, I want to take only the first one in a separate list:

ri!list:

{

{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"}

}

the output should be the following:

local!output: 

{
{output: "OK, id: "abcd", description: "hello"}, 
{output: "OK", id: "yxz", description: "bye"},
{output: "OK", id: "opt", description: "ok"}
}


    Best answer by mikes0011

    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":

    1. 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)
    2. iterate over that list of IDs and get lists of indexes of the index locations in the initial dictionary for the current id ("wherecontains()")
    3. (can possibly be done at the same moment as step 2) - narrow down to just the first index for each item
    4. 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
      )
    )

    3 replies

    mikes0011
    mikes0011Answer
    Brainy
    October 16, 2024

    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":

    1. 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)
    2. iterate over that list of IDs and get lists of indexes of the index locations in the initial dictionary for the current id ("wherecontains()")
    3. (can possibly be done at the same moment as step 2) - narrow down to just the first index for each item
    4. 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
      )
    )

    chiarag0001
    October 18, 2024

    Thank you Mike

    somasundaram.d
    October 17, 2024

    You can achieve it using foreach(), index() and wherecontains()

    a!localVariables(
      local!list: {
        {
          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: union(local!list.id, local!list.id),
      a!forEach(
        items: local!uniqueIds,
        expression: index(
          index(
            local!list,
            wherecontains(fv!item, touniformstring(local!list.id)),
            null
          ),
          1,
          null
        )
      )
    )