appian and maps

Hello,

I am trying to represent the following structure using maps in Appian (for those familiar with C# or Java ... something equivalent to Dictionary<int, List<Object>):

So the list looks something like this:

{
 {
    taskId: 100,
    dependsOnTaskId: 101
  },
 {
    taskId: 100,
    dependsOnTaskId: 121
 },

 {
    taskId: 101,
    dependsOnTaskId: 123
 },

 {
    taskId: 103,
    dependsOnTaskId: 0
 },

 {
    taskId: 123,
    dependsOnTaskId: 5
 },
}

A task Id might have none or multiple unique dependencies (there are many other constrains but at this point I will just focus on the most basic structure)

After processing this list, I would like to have a map as follows:

{

{

taskId :100 dependencies: 101, 121

},

{

taskId :101 dependencies: 123

},

{

taskId :103 dependencies:

},

{

taskId :123 dependencies: 5

}

}

I am able to build this structure in a process model using a loop but performance seems to be an issue here since the node that calls the expression rule and then builds the map takes more than a minute to process a list with less than a hundred items. Moreover, there is the activity chaining...  I often hit the maximum limit of chains(I know this is a configuration parameters and could potentially be increased, but since the list will be constantly growing, I don't think that is the ideal solution).

The thing is that moving the execution to an expression rule and using a for loop doesn't work: on each iteration, the for loop doesn't take into account any changes made on the previous iteration. Therefore, the result is a flat list of maps with the same structure as the initial list (tasks are not being grouped). I was hoping there will be a way to pass parameters "by reference" but this seems to be a foreign concept in Appian (except in process models I know).

Any advice /help would be greatly appreciated!

Thank you

  Discussion posts and replies are publicly visible

Parents
  • Hi - this seems to work:

    a!localVariables(
      local!sourceData: {
        a!map(taskId: 100, dependsOnTaskId: 101),
        a!map(taskId: 100, dependsOnTaskId: 121),
        a!map(taskId: 101, dependsOnTaskId: 123),
        a!map(taskId: 103, dependsOnTaskId: 0),
        a!map(taskId: 123, dependsOnTaskId: 5)
      },
      local!result: a!forEach(
        items: local!sourceData.taskId,
        expression: a!map(
          taskId: fv!item,
          dependencies: local!sourceData.dependsOnTaskId[wherecontains(fv!item, local!sourceData.taskId)]
        )
      ),
      fn!union(local!result,local!result)
    )

    ...with output of:

    I did notice that your expected output value for 'dependancies' for taskId 103 is blank, whereas your source data has a value of 0. I am assuming you wanted 0. If not then you'll have to add a specific clause to output 'null' when the actual value is 0.

    If you want an explanation as to what's going on  I'm happy to provide you with one.

  • Hello ,

    Thank you so much for your quick replay, I very much appreciate it.

    How would you prevent adding circular and duplicated tasks?

    {
     {
        taskId: 100,
        dependsOnTaskId: 101
      },
     {
        taskId: 100,
        dependsOnTaskId: 121
     },

     {
        taskId: 101,
        dependsOnTaskId: 123
     },

     {
        taskId: 103,
        dependsOnTaskId: 0
     },

     {
        taskId: 123,
        dependsOnTaskId: 100
     },

    /*duplicated node*/

    {
        taskId: 123,
        dependsOnTaskId: 100
     }
    }

     100 -> 101 -> 123 -> 100 (circular dependency) 

    Thank you again for your time!

  • Well that's a totally different ball game...

    Circular Dependency: firstly, are you asking how to prevent such a scenario being written to this data structure in the first place, or how to extend the current code to take your data structure generate something that does not have such a dependency (and if so, what are the rules that govern this?)

    Duplicate Node: I already showed you how to removed duplicates for the output by using fn!union() so you can use that on your input before you process it

  • 0
    Certified Lead Developer
    in reply to Stewart Burchell

    I was thinking can we create a temporary CDT which can have a column of multiple type.

  • Hi there again,

    Duplicate node: yes, figured that one out already, thank you!

    Circular dependency: Ideally, the verification would be done while creating the map from the list, eliminating this way, the need to reprocess it later on. The initial list is arbitrary, I do not have control over the different items might contain. However, I do have to guarantee that no circular dependencies are created. 

    A circula dependency could potentially happen at any moment ( [->] translates to  "depends on") 

    a->a

    a->b->a

    a->b->c->b

    a->b->c->a

    a->b->c->x->x

    ...

    I am not sure at this time what would be more efficient, preventing such an scenario or extending the current code as you mentioned.

    Thank you again

  • The approach I would take would be to break the problem down into some smaller problems:

    1. generate the output a per my original example
    2. remove duplicate nodes from the output
    3. remove the circular dependencies

    So I need to know the "rules" that you want to apply for step 3. What should the result be for the following examples?

    • a->a - should that end up as just a ?
    • a->b->a - should that end up as a->b ? or b->a ?
    • a->b->c->b - should that end up as a->b->c ? 
    • a->b->c->a - should that end up as a->b->c ? or b->c->a ?
    • a->b->c->x->x - should that end up as a->b->c->x ?

    On easy to implement option might be just to remove the duplicate items, but that might not be the right answer, so it depends on what rules you want to apply as to what the solution needs to look like.

  • Hello Stewart,

    Your approach sounds good! 

    If a new dependency is going to cause a circular dependency, it should be discarded. Therefore: 

    • a->a - should that end up as just a ? Yes
    • a->b->a - should that end up as a->b ? or b->a ? a->b
    • a->b->c->b - should that end up as a->b->c ? Yes
    • a->b->c->a - should that end up as a->b->c ? or b->c->a ? a->b->c
    • a->b->c->x->x - should that end up as a->b->c->x ? Yes

    Thank you

Reply
  • Hello Stewart,

    Your approach sounds good! 

    If a new dependency is going to cause a circular dependency, it should be discarded. Therefore: 

    • a->a - should that end up as just a ? Yes
    • a->b->a - should that end up as a->b ? or b->a ? a->b
    • a->b->c->b - should that end up as a->b->c ? Yes
    • a->b->c->a - should that end up as a->b->c ? or b->c->a ? a->b->c
    • a->b->c->x->x - should that end up as a->b->c->x ? Yes

    Thank you

Children