SortBy
This transformer will sort an array of dictionary values by keys in ascending or descending order.
python · Filters And Transformers
Source
import json from collections import OrderedDict 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 icluding period charactors. 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 charactors 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 class Key: """ This is a class to provide you a key from an any types of values to sort it. That allows you to sort values even if them have different types of values. The key given by Key.get() can be used for list.sort(). """ def __init__(self, value: Any, path: Optional[str]) -> None: """ Initialize the key. :param value: The value to set key, or the node from which to get the value if the `path` is given. :param path: The path to get values in the node. """ self.__value = value if path is None else demisto_get(value, path) def __get_type_order(self) -> int: if self.__value is None: return 0 elif isinstance(self.__value, bool): return 1 elif isinstance(self.__value, int | float): return 2 elif isinstance(self.__value, str): return 3 else: return 4 def __get_key(self) -> Any: def __get(value: Any) -> Any: if value is None: return 0 elif isinstance(value, bool | int | float | str): return value elif isinstance(value, dict): return OrderedDict((k, __get(value[k])) for k in sorted(value.keys())) elif isinstance(value, list): return [__get(v) for v in value] else: return value v = __get(self.__value) if v is None or isinstance(v, bool | int | float | str): return v else: return json.dumps(v) def get(self) -> tuple[int, Any]: """ Get the key from the value. :return: The key which can be used for list.sort(). """ return self.__get_type_order(), self.__get_key() def main(): try: args = assign_params(**demisto.args()) if value := args.get("value", []): descending_keys = argToList(args.get("descending_keys")) if paths := argToList(args.get("keys")): for path in reversed(paths): value.sort(key=lambda x: Key(x, path).get(), reverse=path in descending_keys) else: descending = len(descending_keys) == 1 and descending_keys[0] == "*" value.sort(key=lambda x: Key(x, None).get(), reverse=descending) 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 sort an array of dictionary values by keys in ascending or descending order.
When values have different types of data, the hierarchy is: null < bool < int/float < str < other (null is top in ascending order).
Script Data
| Name | Description |
|---|---|
| Script Type | python3 |
| Tags | transformer, general |
| Cortex XSOAR Version | 6.8.0 |
Inputs
| Argument Name | Description |
|---|---|
| value | The array to sort. |
| keys | Comma-separated list of ordering-keys specifying a sorting hierarchy |
| descending_keys | Comma-separated list of keys to sort in descending order. ‘*’ is the special symbol to sort the array given without `keys` in descending order. |
Outputs
There are no outputs for this script.
Examples-1
Here is a table for the sorting samples in the Examples-1.
| Name | Country | Score |
|---|---|---|
| Alex | US | 30 |
| Kate | US | 50 |
| Chris | US | 20 |
| Janet | Australia | 50 |
| Steve | Australia | 40 |
| Dora | Australia |
The JSON data is below to be given to the value argument parameter of the transformer for the samples.
[
{
"Name": "Alex",
"Country": "US",
"Score": 30
},
{
"Name": "Kate",
"Country": "US",
"Score": 50
},
{
"Name": "Chris",
"Country": "US",
"Score": 20
},
{
"Name": "Janet",
"Country": "Australia",
"Score": 50
},
{
"Name": "Dora",
"Country": "Australia"
}
]
Sort by Country in ascending order.
keys: Country
descending_keys:
Output
It will give you the result like this. But the order except for the Country is not guaranteed.
| Name | Country | Score |
|---|---|---|
| Janet | Australia | 50 |
| Dora | Australia | |
| Alex | US | 30 |
| Kate | US | 50 |
| Chris | US | 20 |
[
{
"Name": "Janet",
"Country": "Australia",
"Score": 50
},
{
"Name": "Dora",
"Country": "Australia"
},
{
"Name": "Alex",
"Country": "US",
"Score": 30
},
{
"Name": "Kate",
"Country": "US",
"Score": 50
},
{
"Name": "Chris",
"Country": "US",
"Score": 20
}
]
Sort by Country in ascending order, and sort by Score in ascending order with keeping the order by Country.
keys: Country, Score
descending_keys:
Output
It will give you the result like this. But the order except for the Country and Score is not guaranteed.
| Name | Country | Score |
|---|---|---|
| Dora | Australia | |
| Janet | Australia | 50 |
| Chris | US | 20 |
| Alex | US | 30 |
| Kate | US | 50 |
[
{
"Name": "Dora",
"Country": "Australia"
},
{
"Name": "Janet",
"Country": "Australia",
"Score": 50
},
{
"Name": "Chris",
"Country": "US",
"Score": 20
},
{
"Name": "Alex",
"Country": "US",
"Score": 30
},
{
"Name": "Kate",
"Country": "US",
"Score": 50
}
]
Sort by Country in ascending order, and sort by Score in descending order with keeping the order by Country.
keys: Country, Score
descending_keys: Score
Output
It will give you the result like this. But the order except for the Country and Score is not guaranteed.
| Name | Country | Score |
|---|---|---|
| Janet | Australia | 50 |
| Dora | Australia | |
| Kate | US | 50 |
| Alex | US | 30 |
| Chris | US | 20 |
[
{
"Name": "Janet",
"Country": "Australia",
"Score": 50
},
{
"Name": "Dora",
"Country": "Australia"
},
{
"Name": "Kate",
"Country": "US",
"Score": 50
},
{
"Name": "Alex",
"Country": "US",
"Score": 30
}
{
"Name": "Chris",
"Country": "US",
"Score": 20
}
]
Examples-2
Here is an array for the sorting samples in the Examples-2.
It will be given to the value argument parameter of the transformer for the samples.
[
{
"key": "value1"
},
2,
0.5,
0,
1,
null,
"aaa",
"ZZZ"
]
Sort in ascending order.
keys:
descending_keys:
Output
[
null,
0,
0.5,
1,
2,
"ZZZ",
"aaa",
{
"key": "value1"
}
]
Sort in descending order.
keys:
descending_keys: *
Output
[
{
"key": "value1"
},
"aaa",
"ZZZ",
2,
1,
0.5,
0,
null
]