List

Construct

Constructs an array with values stored at numbered keys.

Input Fields

  • *User-Defined*: Here, you will set up the structure of your list, by creating a schema with indices and values. The keys for each item must be the index that you want it placed in within your new list. The highest number integer specified in your schema will be the latest populated index, with all previous values set to null, unless otherwise specified.   

Output Fields

  • list: The list that was created as the result of this module. Note- the output defaults to an array of object, if you would like to change the type, change the “_type” key.

Examples

Here’s an example that illustrates how your keys and values are set up in a List.Construct. In this case, the keys are intentionally out of order, to illustrate that list order is determined by the key used. Also, this illustrates that undefined indices within the constructed list are automatically set to null.

{
    "brick": "list.construct",
    "id": "BJ5s2",
    "inputs": {
        "0": {
            "item": "Thing0"
        },
        "2": {
            "_type": "object",
            "_array": false,
            "_value": {
                "item": "Thing2"
            }
        }
    },
    "outputs": {
        "list": {
            "_type": "object",
            "_array": true
        }
    }
}

Resulting list:

"list": [  
  {  "item": "Thing0"  },  
  null,  
  {  "item": "Thing2"  }  
]

Filter

Filter a collection by applying a flow to each element. Each flow invocation that returns false will remove the associated element from the output array.

Input Fields

  • concurrency: The concurrency rate that the filtering occurs with
  • flow: The flow that will serve to filter the specified list. This flow must end with a true or false value. All items that run through this flow and result as “false” are removed from the list.
  • list: The list that will have the specified filtering operations performed on it.

Output Fields

  • list: The resulting, filtered list

Filter By 

Filter a collection by comparing the value for each element at a path to a provided value. The comparison is dictated by an input operation: one of ==, !=, >, <, >=, or <=.

Input Fields

  • comparison: The value that will be used to compare against each item in the provided list.
  • list: The list that will have the specified filtering operations performed on it.
  • operator: The operator that will be used to compare the given path of each item in the provided list against a comparison value.
  • path: The path inside of each item in the list that will be used to filter against.

Output Fields

  • list: The resulting, filtered list

Find

Find an element in a collection by applying a flow to each one in series and returning the first element for which the associated flow returns true.

Input Fields

  • flow: The flow that will serve to search through the specified list. This flow must end with a true or false value. The first item to return as true will be set as the output for this module.
  • list: The list that will be searched.

Output Fields

  • item: The first item in the provided list that returns from the sub-Flow as “true”

Find By

Find an element in a collection by comparing the value for each element at a path to a provided value. The comparison is dictated by an input operation: one of ==, !=, >, <, >=, or <=.

Input Fields

  • comparison: The value that will be used to compare against each item in the provided list.
  • list: The list that will have the specified filtering operations performed on it.
  • operator: The operator that will be used to compare the given path of each item in the provided list against a comparison value.
  • path: The path inside of each item in the list that will be used to filter against.

Output Fields

  • item: The first value inside the provided list that results as “true” with the given tests.

Flatten 

Create a recursively flattened array from an array of possibly embedded arrays.

Input Fields

  • lists: An array of lists you would like to flatten into one list. You may place any number of lists in this array, either through a comma-separated list of Mustache references or through specifically enumerated lists.

Output Fields

  • list: The resulting, flattened list.

Join

Concatenate the elements of an array into a string, combined by a delimiting string.

Input Fields

  • delimiter: The string you would like to use in-between each item from your list in the newly composed string.
  • list: The list of items that you would like to join together as a string.

Output Fields

  • string: The resulting string, that contains each item of your provided list, separated by the delimiter string input.

Map

Map a collection to another collection by processing each element with a flow and storing the resulting output. The output array will have the result of each inner flow in the same order as the input array.

Input Fields

  • concurrency: The concurrency of the map operation.
  • flo: The Flow that will process each item in your given list. You may set “_value” to either another method’s name (See example 1), or you can place a module inline for simple tasks (See example 2). 
  • list: The list of items that will be iterated over and changed with the provided Flow.

Output Fields

  • new list: The list of items after they have been processed by the given Flow.

Example 1

This is an example of a List.Map module that uses a separate metadata method to perform an operation on each item in a list. This technique should be used when the operation you want to perform requires more than a couple of modules to complete. If the operation would only be one or two modules, you might consider using in-line modules. See the other List.Map for more details if this is the case. Using List.Map with a separate metadata method for processing requires you to add a “variant” flag in the metadata method you will be using. Information about this can be found in the Forge Documentation under “Metadata Methods: Metadata Method Classes”. To be able to refer to each item in the list, you must set a name for each item. To do so, select the name of your metadata method on the left-hand menu. Then place the “variant” object as a top-level item. 

{ 
  "name": "[metadataMethodName]", 
  "kind": "metadata", 
  "variant": { 
    "_type": "object", 
    "_key": "itemName", 
    "_array": false
  }, 
  "zebricks": [ 
    { 
    //modules you create will go here 
    } 
  ] 
 } 

Inside the “variant” object, set the “_key” object to the name you would like to use. After this has been set, you may refer to the item throughout that metadata method by using a Mustache reference with the name, like so: {{itemName}}. Depending on what each item in the list you are iterating over is, you may have to change _type and _array to match accordingly.

Example 2

If you are performing a relatively simple set of operations on each item inside your list, in-line (anonymous) Flows is a good way to go. This style allows you to forego creating helper function, for a more “trackable” set of logic in one place.

To use this, set “_value” of your “flo” input to be an object or array of objects, if you’re doing more than one module operation in your anonymous child flow. Each one of those objects will be a direct copy and paste of a normal connector module.

As you can see in the following example, the “flo” contains a single “object.construct” module inside of it- and will therefore perform an object construct on each item in the original list. Additionally, in-line Flows still allow you to still reference each item in the list, without having to define the “variant” object. With in-line Flows, all you have to do is set the top-level “item” field to be the name that you would like to call each item in your list. In the below example, each item in my list would be referred to using “{{itemName}}” inside my in-line Flow.

{
   "brick": "list.map",
   "id": "ID",
   "item": "itemName",
   "inputs": {
     "list": {
       "_availableTypes": [
         "*"
       ],
       "_type": "object",
       "_array": true,
       "_value": "{{listNameHere}}"
     },
     "flo": {
       "_type": "flo",
       "_array": false,
       "_value": {
         "brick": "object.construct",
         "id": "ID",
         "inputs": {
           "NewFormat" : "{{itemName.path}}"
         },
         "outputs": {
           "output": {
             "_type": "object",
             "_array": false
           }
         }
       }
     },
     "concurrency": {
       "_type": "number",
       "_array": false,
       "_value": 0
     }
   },
   "outputs": {
     "new list": {
       "_type": "object",
       "_array": true
     }
   }
 }

Map Filter

Filter a collection by applying a flow to each element. Each flow invokation that returns false will remove the associated element from the output array. However, instead of returning the filtered input collection this will return the filtered output collection. This is analagous to a map followed by a filter.

Inputs

  • concurrency: The concurrency of this filter operation.
  • flo: The flow that will test each item in the provided list. If an item in this list does not pass the test in this flow (returns “false”), that item will be omitted from the new list that is returned from this module. The sub-Flow selected for this input must return a boolean value.
  • list: The list that will be filtered.

Outputs

  • new list: The new list that contains only the items from the original list that passed the filter test.

Reduce

Reduce a collection to an object by applying a flow to each element in series. This is based on the traditional ‘reduce’ operation in a functional programming language. Should not be used to reduce a list into a smaller list. 

Inputs

  • flo: The sub-Flow that will handle the reduction process. You must add a “memo” object to your sub-Flow. See following example or the “Metadata Method: Metadata Method Classes” section in the documentation for more information.
  • *list: *The list that will be reduced.
  • memo: The object that the list will be reduced into. To refer to the memo object in the sub-Flow, you must add a “memo” object inside of your metadata method. See following example or the “Metadata Method: Metadata Method Classes” section in the documentation for more information

Outputs

  • item: The object (or other data type) that the list has been reduced into.

Example 1:

This example will use the List.Reduce module to take in a list, and then reduces that list’s items into a single object. In this particular case we’re going through a list where each item has a field called “in”. This field determines where that item should be stored. Here’s that list:

[ 
 { 
    "name": "item1",
    "in": "A",
    "field" : "value1"
 },
 { 
    "name": "item2",
    "in": "B",
    "field" : "value2"
 }, 
 { 
   "name": "item3",
   "in": "B",
   "field" : "value3"
 }
]

And here’s what the final result will be:

{
    "A": [
        {
            "name": "item1",
            "field": "value1",
            "in": "A"
        }
    ],
    "B": [
        {
            "name": "item2",
            "field": "value2",
            "in": "B"
        },
        {
            "name": "item3",
            "field": "value3",
            "in": "B"
        }
    ]
}

Seeing both of these, we know a couple of things before we even get started:

  •  We will need our memo to start off as an empty object, that we then build on as we iterate through the list
  • While iterating over our original list, we will then create or update the lists inside of our memo object (“A” and “B”)

The first thing we will need to define is the List.Reduce module that will kick off this operation. In this example, it will look like:

{
    "brick": "list.reduce",
    "id": "REDUCE",
    "inputs": {
        "list": {
                "_availableTypes": [
                        "*"
                ],
                "_type": "object",
                "_array": true,
                "_value": <list reference here>
        },
        "memo": {
             "_availableTypes": [
                  "*"
             ],
             "_type": "object",
             "_array": false,
             "_value": {}
         },
        "flo": {
               "_type": "flo",
               "_array": false,
               "_value": "reduceToObject"
          }
    },
    "outputs": {
            "item": {
                "_type": "object",
                "_array": false
          }
     }
}

Next, we will need to add two top-level keys to the child Flow we will be using to process each item in the original list (reduceToObject). One will be the ‘memo’, that we will build on as we iterate through our list. The other is the ‘variant’ that will represent the item we are currently processing as we iterate through our list. We’ll define them like this:

 "variant": { 
    "_type": "object",
    "_key": "item",
    "_array": false
}, 
"memo": {
    "_type": "object",
    "_array": false
}

Now, onto the actual implementation. A couple of notes:

  •  We will be able to refer to and change the memo by using “{{memo}}”. At the end of each run of this child Flow, we will want to make sure that we’ve altered the memo, or else the List.Reduce function will just return an empty object.
  •  I’ve named my ‘variant’ ‘item’, as seen in the “_key” field above.

Here is the inner child Flow, with all bricks underneath: 1) Start by checking to see where this item needs to be placed in our memo object with an object.get that reads the item’s “in” field.

{ 
   "brick": "object.get", 
   "id": "IN", 
   "inputs": {
      "object": { 
          "_type": "object", 
          "_array": false, 
          "_value": "{{item}}" 
       }, 
      "path": { 
          "_type": "string", 
          "_array": false, 
          "_value": "in" 
      } 
    }, 
    "outputs": { 
       "output": { 
           "_type": "string", 
           "_array": false 
         } 
     } 
}

2)  Then we grab the memo and see what’s stored at the item’s “in” value. For example, if the item has “in” set to “A”, we need to grab the “A” key from the memo.

{ 
   "brick": "object.get", 
   "id": "GRAB LIST", 
   "inputs": { 
       "object": { 
       "_type": "object", 
       "_array": false, 
       "_value": "{{memo}}" 
    }, 
    "path": { 
         "_type": "string", 
         "_array": false, 
         "_value": <item's "in" value> 
     } 
  }, 
  "outputs": { 
      "output": { 
          "_type": "object", 
          "_array": true 
       } 
   } 
}

3) We then need to take whatever list was stored at the “in” key for our memo, and add our ‘item’ to it

{ 
    "brick": "list.push", 
    "id": "UPDATED", 
    "inputs": { 
       "item": { 
           "_availableTypes": [ "*" ], 
           "_type": "object",
           "_array": false, 
           "_value": "{{item}}"
        }, 
        "list": { 
           "_availableTypes": [ "*" ],
           "_type": "object", 
           "_array": true, 
           "_value": "{{GRAB LIST.output}}"
         } 
     }, 
     "outputs": { 
         "list": { 
             "_type": "object", 
             "_array": true 
          } 
       }
 }

4) Finally, we just need to update the whole memo item with our updated inner list

{ 
    "brick": "object.set", 
    "id": "NEW MEMO VAL", 
    "inputs": { 
         "object": { 
            "_type": "object", 
            "_array": false, 
            "_value": "{{memo}}" 
         }, 
        "path": { 
             "_type": "string", 
             "_array": false, 
             "_value": "{{item.in}}" 
         }, 
         "value": { 
            "_availableTypes": [ "*" ], 
            "_type": "object", 
            "_array": true, 
            "_value": "{{UPDATED.list}}" 
         } 
      }, 
      "outputs": { 
           "output": { 
              "_type": "object", 
             "_array": false 
            } 
       } 
}

After each iteration, we will now have an updated memo! This completed object is then available as the output from the List.Reduce module.

Sort By

Sort a collection by the value stored at a given path in each element.

Inputs

  • list: The list that will be sorted
  • path: The path that will be used to determine sorting order

Outputs

  • sorted list: The sorted list.

Zip

Takes two arrays of equal length, A and B, and combines them into an array where index i is an array of the form [A[i], B[i]].

Inputs

  • list1: A list to zip together. All items in this list will precede an item in “list2”. This list must be the same length as “list2”
  • list2: A list to zip together. All items in this list will follow an item in “list1”. This list must be the same length as “list1”

Outputs

  • list: The resulting list. This list will be in this form: [list1[i], list2[i]]