Getting One Property Value From Dictionary Based Upon Another Property Value

I have this expression rule and I need to get the value of one of the keys based upon whether another key property is true or false, I have this but doesn't work:

a!localVariables(
  local!myDictionary: {
    {
    item: 1,
    active: true,
    description: "Widget",
    color: "Green"}
    ,{
    item: 2,
    active:false,
    description: "another",
    color: "red"}
  },
  if(
  fn!index(local!myDictionary,"active","") == true,
    fn!index(local!myDictionary,"color",null), "")
)

To explain further: I would want to return the value "Green" from the key property color due to active property being true and not the value "red" because active property is false.

  Discussion posts and replies are publicly visible

  • +1
    Certified Lead Developer

    Close. There are a couple of notes. You should use a!map() instead of dictionaries to help resolve typing mismatch errors. With a dictionary you are probably getting a compare error with a list of variant and boolean. so that line should be more like 

    if(toboolean(fn!index(local!myDictionary,"active","")),

    Note: "if(predicate = true," and "if(predicate," are logically the same

    Line 15 will give you a boolean array of the indices where "active" is true, but wherever you return false, you will get "" returned, so your snippet would return {"Green", ""}. You could store this result and filter out the nulls using filter() or a!forEach(), but I would write this like:

    a!localVariables(
      local!myDictionary: {
        a!map(
          item: 1,
          active: true,
          description: "Widget",
          color: "Green"
        ),
        a!Map(
          item: 2,
          active:false,
          description: "another",
          color: "red"
        )
      },
      index(local!myDictionary.color, where(local!myDictionary.active), {})
    )

  • Hi

    Here's the code:

    a!localVariables(
      local!myDictionary: {
        {
          item: 1,
          active: true,
          description: "Widget",
          color: "Green"
        },
        {
          item: 2,
          active: false,
          description: "another",
          color: "red"
        }
      },
      local!myDictionary.color[fn!wherecontains(true,fn!toboolean(local!myDictionary.active))]
    )

    Here's the result:

    ...and here's an explanation:

    • you can address elements in an array using the square brackets
    • ...so we're looking to extract all of the color attribute values - addressed using local!myDictionary.color - where the corresponding 'active' attribute is true...
    • ...so we use the function 'wherecontains()' which returns the indices in an array that contain the the provided value. So, in our case, fn!wherecontains(true,<the array of local!myDictionary.active>)
    • the expression inside the square brackets returns the indices and is then used to return the values for the array that the square brackets are attached to

    Hope this helps

  • Great explanation with the bullet points. I was not aware you could use functions within the square brackets and the reason why I may have missed something simple as this, but now I know! Thank you for the help! 

  • You could store this result and filter out the nulls using filter() or a!forEach(),

    Could this be a test case (forEach()) IF there were more than one true in the active property? Is this a correct assumption?

  • 0
    Certified Lead Developer
    in reply to here2learn

    Can your expand your question or give an example? I'm not sure what you are asking.

  • Sure: 

    a!localVariables(
      local!myDictionary: {
        a!map(
          item: 1,
          active: true,
          description: "Widget",
          color: "Green"
        ),
        a!Map(
          item: 2,
          active:false,
          description: "another",
          color: "red"
        ),
        a!Map(
          item: 3,
          active:true,
          description: "another des",
          color: "blue"
        )
      },
      index(local!myDictionary.color, where(local!myDictionary.active), {})
    )

    When you mentioned that you would save the results in a forEach() function, the above code now has two true items, in this instance, utilizing a forEach() would produce a list of {Green,Blue}. Is this correct?

  • 0
    Certified Lead Developer
    in reply to here2learn

    The example you just posted works just fine for your desired outcome.

    I was saying you would need a looping function to filter out nulls in your first example if you were to use if(). The if() approach would result in "{"Green", "", "Blue"}". If you wanted just "{"Green", "Blue"}", you would need to get rid of that middle "" element. Here is that example:

    a!localVariables(
      local!myDictionary: {
        {
          item: 1,
          active: true,
          description: "Widget",
          color: "Green"},
        {
          item: 2,
          active:false,
          description: "another",
          color: "red"}
      },
      local!tempResults: if(toboolean(fn!index(local!myDictionary,"active","")),
        fn!index(local!myDictionary,"color",null), 
        ""
      ),
      reject(fn!isnull, local!tempResults)
    )

    Note: At the risk of over-simplification, think of reject() as a specialized a!forEach() in this instance. 

  • OK, I see what you mean now, thank you for the help!