MakePair

This transformer will create a list of dictionary by aggregating elements from two arrays. The one is given by `value` (with `array1_key`), another is given by `array2` (with `array2_key`).

python · Filters And Transformers

Source

from itertools import zip_longest
from typing import Any

import demistomock as demisto  # noqa: F401
from CommonServerPython import *  # noqa: F401


def demisto_get(obj: Any, path: Any) -> Any:
    r"""
    This is an extended function of demisto.get().
    The `path` argument parameter supports a syntax of path escaped with backslash
    in order to support a key including period characters.

    e.g.
       xxx
        + x.y.z
         + zzz

       -> path: xxx.x\.y\.z.zzz

    :param obj: The root node.
    :param path: The path to get values in the node.
    :return: The value(s) specified with `path` in the node.
    """

    def split_context_path(path: str) -> list[str]:
        """
        Get keys in order from the path which supports a syntax of path escaped with backslash.

        :param path: The path.
        :return: The keys whose escape characters are removed.
        """
        nodes = []
        node = []
        itr = iter(path)
        for c in itr:
            if c == "\\":
                try:
                    node.append(next(itr))
                except StopIteration:
                    node.append("\\")
            elif c == ".":
                nodes.append("".join(node))
                node = []
            else:
                node.append(c)
        nodes.append("".join(node))
        return nodes

    if not isinstance(obj, dict):
        return None

    for part in split_context_path(path):
        if obj and part in obj:
            obj = obj[part]
        else:
            return None
    return obj


def make_dict(element1: Any, element2: Any, output_name1: str, output_name2: str, method: str | None) -> dict[str, Any]:
    if method == "array1":
        if isinstance(element1, dict):
            return dict(element1, **{output_name2: element2})
    elif method == "array2":
        if isinstance(element2, dict):
            return dict(element2, **{output_name1: element1})
    elif method == "array1<array2":
        if isinstance(element1, dict):
            if isinstance(element2, dict):
                return dict(element1, **element2)
            else:
                return dict(element1, **{output_name2: element2})
    elif method == "array2<array1":
        if isinstance(element1, dict):
            if isinstance(element2, dict):
                return dict(element2, **element1)
            else:
                return dict(element2, **{output_name1: element1})
    elif method is not None:
        raise DemistoException(f'Invalid parameter was given to "merge_dict" - {method}')

    return {output_name1: element1, output_name2: element2}


def main():
    try:
        args = assign_params(**demisto.args())
        array1 = args.get("value", [])
        if array1_key := args.get("array1_key"):
            array1 = [demisto_get(x, array1_key) for x in array1]

        if not isinstance(array1, list):
            array1 = [array1]

        array2 = args.get("array2", [])
        if array2_key := args.get("array2_key"):
            array2 = [demisto_get(x, array2_key) for x in array2]

        if not isinstance(array2, list):
            array2 = [array2]

        determine_output_length_by = args.get("determine_output_length_by", "shorter")
        if determine_output_length_by == "array1":
            diff = len(array1) - len(array2)
            if diff > 0:
                array2 += [None] * diff
            determine_output_length_by = "shorter"
        elif determine_output_length_by == "array2":
            diff = len(array2) - len(array1)
            if diff > 0:
                array1 += [None] * diff
            determine_output_length_by = "shorter"

        output_name1 = args.get("output_name1")
        output_name2 = args.get("output_name2")
        merge_dict = args.get("merge_dict")
        if determine_output_length_by == "shorter":
            value = [make_dict(e1, e2, output_name1, output_name2, merge_dict) for e1, e2 in zip(array1, array2)]
        elif determine_output_length_by == "longer":
            value = [make_dict(e1, e2, output_name1, output_name2, merge_dict) for e1, e2 in zip_longest(array1, array2)]
        else:
            raise DemistoException(f'Invalid parameter was given to "determine_output_length_by" - {determine_output_length_by}')

        return_results(value)
    except Exception as err:
        # Don't return an error by return_error() as this is transformer.
        raise DemistoException(str(err))


if __name__ in ("__builtin__", "builtins", "__main__"):
    main()

README

This transformer will create a list of dictionary by aggregating elements from two arrays.
The one is given by value (with array1_key), another is given by array2 (with array2_key).

Script Data


Name Description
Script Type python3
Tags transformer, general
Cortex XSOAR Version 6.8.0

Inputs


Argument Name Description
value The array1
array1_key The key or path to get values from the array1 (value)
array2 The array2
array2_key The key or path to get values from the array2
output_name1 The key name in the output dictionary to which each of element of the array1 are given
output_name2 The key name in the output dictionary to which each of element of the array2 are given
determine_output_length_by How to deal with different size lists. (Choose from shorter, longer, array1, or array2)
merge_dict Specify which array will be merged into when each of element is given in dictionary. (Choose from array1, array2, array1|2, or array2|1)

Outputs


There are no outputs for this script.


Examples


Simply create a list of dictionary by aggregating elements from two arrays.

value:

[
  1,
  2,
  3
]

array1_key:

array2:

[
  "a",
  "b",
  "c"
]

array2_key:

output_name1: xxx

output_name2: yyy

determine_output_length_by:

merge_dict:

Output

[
  {
    "xxx": 1,
    "yyy": "a"
  },
  {
    "xxx": 2,
    "yyy": "b"
  },
  {
    "xxx": 3,
    "yyy": "c"
  }
]

Aggregate each of value from the keys given.

value:

[
  {
    "key1": "a",
    "key2": "A"
  },
  {
    "key1": "b",
    "key2": "B"
  },
  {
    "key2": "C"
  }
]

array1_key: key1

array2:

[
  {
    "key3": "x",
    "key4": "X"
  },
  {
    "key3": "y",
    "key4": "Y"
  },
  {
    "key4": "Z"
  }
]

array2_key: key3

output_name1: xxx

output_name2: yyy

determine_output_length_by:

merge_dict:

Output

[
  {
    "xxx": "a",
    "yyy": "x"
  },
  {
    "xxx": "b",
    "yyy": "y"
  },
  {
    "xxx": null,
    "yyy": null
  }
]

Truncate remaining elements of array2 which is longer than array1.

value:

[
  {
    "key1": "a",
    "key2": "A"
  },
  {
    "key1": "b",
    "key2": "B"
  }
]

array1_key: key1

array2:

[
  {
    "key3": "x",
    "key4": "X"
  },
  {
    "key3": "y",
    "key4": "Y"
  },
  {
    "key3": "z",
    "key4": "Z"
  }
]

array2_key: key3

output_name1: xxx

output_name2: yyy

determine_output_length_by: array1

merge_dict:

Output

[
  {
    "xxx": "a",
    "yyy": "x"
  },
  {
    "xxx": "b",
    "yyy": "y"
  }
]

array2 is longer than array1. fill in shorten elements with null.

value:

[
  {
    "key1": "a",
    "key2": "A"
  },
  {
    "key1": "b",
    "key2": "B"
  }
]

array1_key: key1

array2:

[
  {
    "key3": "x",
    "key4": "X"
  },
  {
    "key3": "y",
    "key4": "Y"
  },
  {
    "key3": "z",
    "key4": "Z"
  }
]

array2_key: key3

output_name1: xxx

output_name2: yyy

determine_output_length_by: array2

merge_dict:

Output

[
  {
    "xxx": "a",
    "yyy": "x"
  },
  {
    "xxx": "b",
    "yyy": "y"
  },
  {
    "xxx": null,
    "yyy": "z"
  },
]

Merge each of dictionary element.

value:

[
  {
    "key1": "a",
    "key2": "A"
  },
  {
    "key1": "b",
    "key2": "B"
  }
]

array1_key:

array2:

[
  {
    "key3": "x",
    "key4": "X"
  },
  {
    "key3": "y",
    "key4": "Y"
  }
]

array2_key:

output_name1: xxx

output_name2: yyy

determine_output_length_by:

merge_dict: array1<2

Output

[
  {
    "key1": "a",
    "key2": "A",
    "key3": "x",
    "key4": "X"
  },
  {
    "key1": "b",
    "key2": "B",
    "key3": "y",
    "key4": "Y"
  }
]

Merge each of element into a dictionary.

value:

[
  {
    "key1": "a",
    "key2": "A"
  },
  {
    "key1": "b",
    "key2": "B"
  }
]

array1_key:

array2:

[
  1,
  2
]

array2_key:

output_name1: xxx

output_name2: yyy

determine_output_length_by:

merge_dict: array1

Output

[
  {
    "key1": "a",
    "key2": "A",
    "yyy": 1
  },
  {
    "key1": "b",
    "key2": "B",
    "yyy": 2
  }
]