DedupBy
This transformer will remove elements of the array that contain an identical combination of values for the keys given.
python · Filters And Transformers
Details
| ID | DedupBy |
|---|---|
| Language | python |
| From Version | 6.8.0 |
| Docker Image | demisto/python3:3.12.13.10404775 |
| Tags | transformer general |
README
This transformer will remove elements of the array that contain an identical combination of values for the keys given.
Script Data
| Name | Description |
|---|---|
| Script Type | python3 |
| Tags | transformer, general |
| Cortex XSOAR Version | 6.8.0 |
Inputs
| Argument Name | Description |
|---|---|
| value | The array to deduplicate |
| keys | Comma-separated list of keys to identify a value |
Outputs
There are no outputs for this script.
Examples-1
Here is a table to be used as samples in the Examples-1.
| DestinationIP | SourceIP |
|---|---|
| 1.1.1.1 | 192.168.1.1 |
| 1.1.1.1 | 192.168.1.1 |
| 1.1.1.1 | 192.168.1.2 |
| 1.1.1.1 | 192.168.1.2 |
| 1.1.1.1 | 192.168.1.3 |
| 1.1.1.1 | 192.168.1.3 |
| 2.2.2.2 | 192.168.1.1 |
| 2.2.2.2 | 192.168.1.1 |
| 2.2.2.2 | 192.168.1.2 |
| 2.2.2.2 | 192.168.1.2 |
| 2.2.2.2 | 192.168.1.3 |
| 2.2.2.2 | 192.168.1.3 |
The JSON data is below to be given to the value argument parameter of the transformer for the samples.
[
{
"DestinationIP": "1.1.1.1",
"SourceIP": "192.168.1.1"
},
{
"DestinationIP": "1.1.1.1",
"SourceIP": "192.168.1.1"
},
{
"DestinationIP": "1.1.1.1",
"SourceIP": "192.168.1.2"
},
{
"DestinationIP": "1.1.1.1",
"SourceIP": "192.168.1.2"
},
{
"DestinationIP": "1.1.1.1",
"SourceIP": "192.168.1.3"
},
{
"DestinationIP": "1.1.1.1",
"SourceIP": "192.168.1.3"
},
{
"DestinationIP": "2.2.2.2",
"SourceIP": "192.168.1.1"
},
{
"DestinationIP": "2.2.2.2",
"SourceIP": "192.168.1.1"
},
{
"DestinationIP": "2.2.2.2",
"SourceIP": "192.168.1.2"
},
{
"DestinationIP": "2.2.2.2",
"SourceIP": "192.168.1.2"
},
{
"DestinationIP": "2.2.2.2",
"SourceIP": "192.168.1.3"
},
{
"DestinationIP": "2.2.2.2",
"SourceIP": "192.168.1.3"
}
]
Deduplicate by SourceIP.
keys: SourceIP
Output
It will give you the result below.
It’s guaranteed to keep the original order, and gives you the first record when multiple records are found by collecting keys given.
| DestinationIP | SourceIP |
|---|---|
| 1.1.1.1 | 192.168.1.1 |
| 1.1.1.1 | 192.168.1.2 |
| 1.1.1.1 | 192.168.1.3 |
[
{
"DestinationIP": "1.1.1.1",
"SourceIP": "192.168.1.1"
},
{
"DestinationIP": "1.1.1.1",
"SourceIP": "192.168.1.2"
},
{
"DestinationIP": "1.1.1.1",
"SourceIP": "192.168.1.3"
}
]
Deduplicate by SourceIP and DestinationIP.
keys: SourceIP, DestinationIP
Output
It will give you the result below.
It’s guaranteed to keep the original order, and gives you the first record when multiple records are found by collecting keys given.
| DestinationIP | SourceIP |
|---|---|
| 1.1.1.1 | 192.168.1.1 |
| 1.1.1.1 | 192.168.1.2 |
| 1.1.1.1 | 192.168.1.3 |
| 2.2.2.2 | 192.168.1.1 |
| 2.2.2.2 | 192.168.1.2 |
| 2.2.2.2 | 192.168.1.3 |
[
{
"DestinationIP": "1.1.1.1",
"SourceIP": "192.168.1.1"
},
{
"DestinationIP": "1.1.1.1",
"SourceIP": "192.168.1.2"
},
{
"DestinationIP": "1.1.1.1",
"SourceIP": "192.168.1.3"
},
{
"DestinationIP": "2.2.2.2",
"SourceIP": "192.168.1.1"
},
{
"DestinationIP": "2.2.2.2",
"SourceIP": "192.168.1.2"
},
{
"DestinationIP": "2.2.2.2",
"SourceIP": "192.168.1.3"
}
]
Examples-2
Here is an array to be used as samples in the Examples-2.
It will be given to the value argument parameter of the transformer for the samples.
[
null,
1,
{
"key": "value1"
},
2,
0.5,
0,
0.5,
"aaa",
1,
{
"key": "value1"
},
null,
"aaa",
"ZZZ"
]
Deduplicate an array without keys.
keys:
Output
It will give you the result below.
It’s guaranteed to keep the original order, and gives you the first record when multiple records are found by collecting keys given.
[
null,
1,
{
"key": "value1"
},
2,
0.5,
0,
"aaa",
"ZZZ"
]
import json import DedupBy import demistomock as demisto def test_1(mocker): with open("./test_data/test-1.json") as f: test_list = json.load(f) for case in test_list: value = case["value"] expected = case["result"] for args in case.get("args") or [{}]: keys = args.get("keys") mocker.patch.object(demisto, "args", return_value={"value": value, "keys": keys}) mocker.patch.object(DedupBy, "return_results") DedupBy.main() assert DedupBy.return_results.call_count == 1 ret = DedupBy.return_results.call_args[0][0] assert ret == expected def test_performance_large_input(mocker): """ Given: A large dataset with 10,000 items (100 unique items with 100 duplicates each) When: Deduplicating by SourceIP and DestinationIP keys Then: Should return exactly 100 unique items """ # Create a large dataset with duplicates # Each item is a dict with nested structures large_value = [] num_unique = 100 duplicates_per_item = 100 for i in range(num_unique): # Create multiple duplicates of each unique item for _ in range(duplicates_per_item): large_value.append( { "SourceIP": f"192.168.1.{i}", "DestinationIP": f"10.0.0.{i}", "Port": 443, "Protocol": "HTTPS", "Metadata": { "timestamp": "2026-02-18T00:00:00Z", "severity": "high", "tags": ["network", "security", "monitoring"], }, } ) mocker.patch.object(demisto, "args", return_value={"value": large_value, "keys": "SourceIP,DestinationIP"}) mocker.patch.object(DedupBy, "return_results") DedupBy.main() result = DedupBy.return_results.call_args[0][0] assert len(result) == num_unique, f"Expected {num_unique} unique items, got {len(result)}" def test_performance_comparison_no_keys(mocker): """ Given: A dataset with 2,500 items (500 unique items with 5 duplicates each) containing complex nested objects When: Deduplicating entire objects without specifying keys Then: Should return exactly 500 unique items """ # Create dataset with complex nested objects large_value = [] for i in range(500): for _ in range(5): # 5 duplicates each large_value.append({"id": i, "data": {"nested": {"deep": {"value": f"item_{i}", "list": [1, 2, 3, 4, 5]}}}}) mocker.patch.object(demisto, "args", return_value={"value": large_value}) mocker.patch.object(DedupBy, "return_results") DedupBy.main() result = DedupBy.return_results.call_args[0][0] assert len(result) == 500, f"Expected 500 unique items, got {len(result)}"