Populate CDT with values of Array

Hi,

 

I have a process variable CDT of type array, the CDT has this fields {Title1=,Title2=,Title3=}.

And i have an array with the values {3,4,7,q,a,1,3,9,0}.

And i want to have the PV populated like this: {{Title1=3,Title2=4,Title3=7},{Title1=q,Title2=a,Title3=1},{Title1=3,Title2=9,Title3=0}}

Do you have any suggestions?

It has to be a flexible solution because it has to be used with different CDT's, on the process.

 

Thanks

  Discussion posts and replies are publicly visible

Parents
  • 0
    Certified Lead Developer
    To get any sort of flexible solution you're going to need to more carefully define what the input array will contain, and/or what the CDT properties will be. In your example, your CDT has 3 fields and your array has 9 values, but what if another CDT has 4 fields, or the input array doesn't have a number of values that is a multiple of the number of the CDT fields?
  • Imagine that the array is always multiple with the cdt fields...
  • The code below will give you the expected output for the provided input, but the part about it being generic enough to work with any CDT is a lot trickier. Maybe you can define a rule like the example here for each of the CDTs you know about right and then create a wrapper rule that will act as a dispatcher.

    = load(
    /* ri!data is List of Text String, ri!fieldCount is Integer */
    local!count: count(ri!data)/ri!fieldCount,

    a!forEach(
    enumerate(local!count),
    {
    Title1: index(ri!data, 1+ri!fieldCount*fv!item, null),
    Title2: index(ri!data, 2+ri!fieldCount*fv!item, null),
    Title3: index(ri!data, 3+ri!fieldCount*fv!item, null)
    }
    )
    )
  • 0
    Certified Lead Developer
    in reply to Carlos Santander

    One thought I'd had is if the CDT fields are known, maybe we could pass them in as an array too.

    It can be tricky to dynamically name the dictionary field names, but one trick I've seen used before is to manually construct a JSON string and then back-translate that to actual dictionary data.  I've had moderate success so far with this approach (note the rule inputs here are "fields" and "data", both text strings):

    with(
     
      local!numFields: length(ri!fields),
     
      /* for the count we need to do "ceiling" on the division result or else we
      risk truncating any remainders in the data array.  doing it this way, the
      data array doesn't need to be an even multiple of the number of fields. */
      local!count: ceiling(count(ri!data) / local!numFields),
     
      local!jsonString: "[" &
      joinarray(
        a!foreach(
          enumerate(local!count),
          with(
            /* i assume this is the only way we can access the fv!item value from inside
            the lower nested a!forEach call - pretty painless at the end of the day but
            it took me a while to figure out to try this */
            local!cdtCount: fv!item
            ,
            "{" &
            joinarray(
              a!forEach(
                ri!fields,
                """" & fv!item & """:""" &
                index(
                  ri!data,
                  local!cdtCount * local!numFields + fv!index,
                  null()
                )
                & """"
              ),
              ","
            )
            & "}"
            
          )
        ),
        ","
      )
      & "]",
     
      a!fromJson(
        local!jsonString
      )
    )

    Side note 1: a!forEach really is a savior.
    Side note 2: you really want to use with() instead of load() in this rule, at least if it ever has even the slightest chance of being called from a SAIL form or anything, because load() will cause weird side-effects that catch someone off-guard.

  • 0
    A Score Level 1
    in reply to Mike Schmitt
    for getting dynamic fields of a cdt follow this code snippet that should work dynamically
    apply(
    xpathsnippet(
    _,
    "local-name(/*)"
    ),
    xpathsnippet(
    toxml(
    ri!cdt
    ),
    "/*/*"
    )
    )
Reply Children