split input to chunks with python

cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

split input to chunks with python

L2 Linker

Hi,

 

I'm trying to build an automation which would take an array of objects as an input, split it to chunks of specified number and put in the context. E.g. I have 36 IP addresses, i want it to split to chunks of 10. The end result would be having them in a context - 3 keys having 10 IPs and on key having the remaining 6 IPs.

I can set the split logic in python but i struggle with returning it into context. Any ideas?

 

Output sample:

 

Antanas_0-1665477516583.png

 

Curious Fellow
1 accepted solution

Accepted Solutions

L3 Networker

This is certainly possible. Firstly you would need to decide what Context key name to put them under. After you have decided, generally we use 

return_results(command_results)

where "command_results" is a CommandResults object (for which the documentation on how to use it is here

 

 

As an example (and assuming you have a scrip that has an argument input called "ips"):

 

# Get the arguments
args = demisto.args()
ips = args.get('ips')

# Check that the input is either an array or can be split
if not isinstance(ips, list):
    try:
        ips = ips.split(",")
    except Exception as err:
        return_error(f'The provided input was not an array or CSV data:\n\n{err}')

# How many IPs to break the array into
set_count = 10

# Create a temporary store for the sub-lists
return_data = []

# Iterate each set of <set_count> ips
while len(ips) > set_count:
    return_data.append(ips[0: (set_count)])
    [ips.pop(0) for x in range(set_count)]

# Add the remaining IPs as their own sized array
return_data.append(ips)

# Create the final returned data array
results = []

# Create an index for the set number
set_number = 0

# Iterate throught the arrays and place them into a suitable format
for item in return_data:
    results.append(
        {
            'set': set_number,
            'ips': item
        })
    set_number += 1

# Build the command results object
command_results = CommandResults(
    outputs_prefix='IPSets',
    outputs_key_field=['set'],
    outputs=results,
    readable_output=tableToMarkdown('IPs', results, ['set', 'ips'])
    )
    
# Return the command results object
return_results(command_results)

 

The result in the context is an array containing dictionaries. Each dictionary has a set number (to avoid duplicates) and the actual IPs.

 

I hope this helps.

 

Regards


Adam

View solution in original post

3 REPLIES 3

L3 Networker

This is certainly possible. Firstly you would need to decide what Context key name to put them under. After you have decided, generally we use 

return_results(command_results)

where "command_results" is a CommandResults object (for which the documentation on how to use it is here

 

 

As an example (and assuming you have a scrip that has an argument input called "ips"):

 

# Get the arguments
args = demisto.args()
ips = args.get('ips')

# Check that the input is either an array or can be split
if not isinstance(ips, list):
    try:
        ips = ips.split(",")
    except Exception as err:
        return_error(f'The provided input was not an array or CSV data:\n\n{err}')

# How many IPs to break the array into
set_count = 10

# Create a temporary store for the sub-lists
return_data = []

# Iterate each set of <set_count> ips
while len(ips) > set_count:
    return_data.append(ips[0: (set_count)])
    [ips.pop(0) for x in range(set_count)]

# Add the remaining IPs as their own sized array
return_data.append(ips)

# Create the final returned data array
results = []

# Create an index for the set number
set_number = 0

# Iterate throught the arrays and place them into a suitable format
for item in return_data:
    results.append(
        {
            'set': set_number,
            'ips': item
        })
    set_number += 1

# Build the command results object
command_results = CommandResults(
    outputs_prefix='IPSets',
    outputs_key_field=['set'],
    outputs=results,
    readable_output=tableToMarkdown('IPs', results, ['set', 'ips'])
    )
    
# Return the command results object
return_results(command_results)

 

The result in the context is an array containing dictionaries. Each dictionary has a set number (to avoid duplicates) and the actual IPs.

 

I hope this helps.

 

Regards


Adam

L2 Linker

Hi @ABurt ,

This does exactly what I needed, thanks! I generalized your script to be used not only for IP's and added additional input variables. I'm pasting the updating code for the reference if anyone wants to reuse it. Many thanks again!

commonfields:
  id: b343683b-cc7a-4481-82d4-e089cf52e41c
  version: 32
vcShouldKeepItemLegacyProdMachine: false
name: Split
script: |-
  # Get the arguments
  args = demisto.args()
  items = args.get('items')
  maxitems = args.get('maxitems')
  set_count=int(maxitems)


  output_key = args.get('outputkey')

  # Check that the input is either an array or can be split
  if not isinstance(items, list):
      try:
          items = items.split(",")
      except Exception as err:
          return_error('The provided input was not an array or CSV data:\n\n{err}')


  # Create a temporary store for the sub-lists
  return_data = []

  # Iterate each set of <set_count> items
  while len(items) > set_count:
      return_data.append(items[0: (set_count)])
      [items.pop(0) for x in range(set_count)]

  # Add the remaining Items as their own sized array
  return_data.append(items)

  # Create the final returned data array
  results = []

  # Create an index for the set number
  set_number = 0

  # Iterate throught the arrays and place them into a suitable format
  for item in return_data:
      results.append(
          {
              'set': set_number,
              'items': item
          })
      set_number += 1

  # Build the command results object
  command_results = CommandResults(
      outputs_prefix=output_key,
      outputs_key_field=['set'],
      outputs=results,
      readable_output=tableToMarkdown('Items', results, ['set', 'items']),
      )

  # Return the command results object
  return_results(command_results)
type: python
tags: []
comment: This will split the input array into chunks of *maxitems*
enabled: true
args:
- name: items
  required: true
  description: an array of items to be split
  isArray: true
- name: maxitems
  required: true
  description: number of items in a chunk
- name: outputkey
  required: true
  description: Parent output key
scripttarget: 0
subtype: python3
pswd: ""
runonce: false
runas: DBotWeakRole
engineinfo: {}
mainengineinfo: {}

 

Curious Fellow

L0 Member

Here is some generic Python code to split a list into chunks of 10.

vals = list(range(0,32)) # test data
chunks = [vals[i:i+10] for i in range(0,len(vals),10)]
print(chunks)
  • 1 accepted solution
  • 2765 Views
  • 3 replies
  • 0 Likes
Like what you see?

Show your appreciation!

Click Like if a post is helpful to you or if you just want to show your support.

Click Accept as Solution to acknowledge that the answer to your question has been provided.

The button appears next to the replies on topics you’ve started. The member who gave the solution and all future visitors to this topic will appreciate it!

These simple actions take just seconds of your time, but go a long way in showing appreciation for community members and the LIVEcommunity as a whole!

The LIVEcommunity thanks you for your participation!