cancel
Showing results for 
Search instead for 
Did you mean: 
Reply
Chris66
Frequent Visitor

Chunking an array down to manageable groups

I have an array of email addresses like this:

 

[

"email@email.com",

"another@email.com",

"qwerty@abc.com"

]

 

The array can contain anywhere from 1 to thousands of emails. I want to change the array so that the emails are in groups of 300 e.g.

 

[

{

"email@email.com",

"another@email.com",

"qwerty@abc.com"

...to 300

},

{

"more@email.com"

...to another 300

}

]

 

What is the best way to achieve this?

1 ACCEPTED SOLUTION

Accepted Solutions
eliotcole
Power Participant
Power Participant

Quick Answer

You will need to use the take() and skip() functions in an expression.

 

It's best to do this with the length() of the original array in mind.

 

If you're already pretty good with the logic side, then that should be all you need.

 

Solution

Here's my flow to handle this, you will replace the "3" with "100".

Full Flow LogicFull Flow Logic

 

This could be minimised a bit by moving some of the actions into expressions, but this shows you the logic I was aiming for.

 

I will edit in explanation shortly.

 

You can read on if you like.

 

Logic

Essentially, this works out how many runs are needed to divide the array into chunks of 3 (100 for you), then, for the set amount of turns, it will set the arrayVAR from the arrayWorkerVAR, with increasingly less (by 3) items than before.

 

Each run, it will also place those three deleted items into an object that will be placed into the newArrayVAR array.

 

Expressions/Code Used

Initialize divvyVAR

This looks more complicated than it is (see explanation) but essentially a normal division doesn't see the "remainder" so I had to see if the number of loops needed one more.

 

if(contains(string(div(float(length(variables('arrayVAR'))), 3)), '.'), add(div(length(variables('arrayVAR')), 3), 1), div(length(variables('arrayVAR')), 3))

 

 

jsonObject

This uses the take() function to take the first 3 items from the arrayVAR variable and create a new array.

The code:

 

{
  "chunk": @{take(variables('arrayVAR'), 3)}
}

 

The expression within:

 

take(variables('arrayVAR'), 3)

 

 

Set arrayWorkerVAR

This uses the skip() function to skip over the first 3 items in the arrayVAR variable, to create a new array.

 

The reason the flow needs an extra array here, is because you cannot set a variable's value from itself.

 

skip(variables('arrayVAR'), 3)

 

 

Detailed Explanation for the Long IF Statement in divvyVAR

 

Explaining quickly the basic functions:

  • length() - This counts the number of entries in an array or characters in a string.
  • float() - This formats a number in to a floating point type, allowing decimal points in any further actions.
  • div() - In two parts separated by a comma this will divide the second number from the first.
  • string() - This converts any other data type into a text string.
  • contains() - In two parts this checks the first part (a string or array) before the comma, for the second part after it.
  • add() - Adds any numbers (split by commas) to each other.
  • if() - In three parts separated by commas, if the first part is 'true' this will return the value of the second part, but if it is 'false' it will return the third part.

 

So ... if I get a floating point number from my division, then I will need an extra step to catch the remainder of the items in the array ... meaning:

 

IF - The result of dividing the number of entries in the original array produces a number with a decimal point, then the contains() function will return TRUE

 

THEN - Add 1 to the number of a *normal* (not floating point) division of the length.

 

ELSE - Just take the normal division of the number.

 

View solution in original post

3 REPLIES 3
eliotcole
Power Participant
Power Participant

Quick Answer

You will need to use the take() and skip() functions in an expression.

 

It's best to do this with the length() of the original array in mind.

 

If you're already pretty good with the logic side, then that should be all you need.

 

Solution

Here's my flow to handle this, you will replace the "3" with "100".

Full Flow LogicFull Flow Logic

 

This could be minimised a bit by moving some of the actions into expressions, but this shows you the logic I was aiming for.

 

I will edit in explanation shortly.

 

You can read on if you like.

 

Logic

Essentially, this works out how many runs are needed to divide the array into chunks of 3 (100 for you), then, for the set amount of turns, it will set the arrayVAR from the arrayWorkerVAR, with increasingly less (by 3) items than before.

 

Each run, it will also place those three deleted items into an object that will be placed into the newArrayVAR array.

 

Expressions/Code Used

Initialize divvyVAR

This looks more complicated than it is (see explanation) but essentially a normal division doesn't see the "remainder" so I had to see if the number of loops needed one more.

 

if(contains(string(div(float(length(variables('arrayVAR'))), 3)), '.'), add(div(length(variables('arrayVAR')), 3), 1), div(length(variables('arrayVAR')), 3))

 

 

jsonObject

This uses the take() function to take the first 3 items from the arrayVAR variable and create a new array.

The code:

 

{
  "chunk": @{take(variables('arrayVAR'), 3)}
}

 

The expression within:

 

take(variables('arrayVAR'), 3)

 

 

Set arrayWorkerVAR

This uses the skip() function to skip over the first 3 items in the arrayVAR variable, to create a new array.

 

The reason the flow needs an extra array here, is because you cannot set a variable's value from itself.

 

skip(variables('arrayVAR'), 3)

 

 

Detailed Explanation for the Long IF Statement in divvyVAR

 

Explaining quickly the basic functions:

  • length() - This counts the number of entries in an array or characters in a string.
  • float() - This formats a number in to a floating point type, allowing decimal points in any further actions.
  • div() - In two parts separated by a comma this will divide the second number from the first.
  • string() - This converts any other data type into a text string.
  • contains() - In two parts this checks the first part (a string or array) before the comma, for the second part after it.
  • add() - Adds any numbers (split by commas) to each other.
  • if() - In three parts separated by commas, if the first part is 'true' this will return the value of the second part, but if it is 'false' it will return the third part.

 

So ... if I get a floating point number from my division, then I will need an extra step to catch the remainder of the items in the array ... meaning:

 

IF - The result of dividing the number of entries in the original array produces a number with a decimal point, then the contains() function will return TRUE

 

THEN - Add 1 to the number of a *normal* (not floating point) division of the length.

 

ELSE - Just take the normal division of the number.

 

View solution in original post

This is fantastic thank you, I will try this out today and let you know how I get on.

You, sir, are a fantastic human being. This does exactly what I wanted! Very comprehensive answer and well explained, thank you so much.

Helpful resources

Announcements
UG GA Amplification 768x460.png

Launching new user group features

Learn how to create your own user groups today!

Community Connections 768x460.jpg

Community & How To Videos

Check out the new Power Platform Community Connections gallery!

M365 768x460.jpg

Microsoft 365 Collaboration Conference | December 7–9, 2021

Join us, in-person, December 7–9 in Las Vegas, for the largest gathering of the Microsoft community in the world.

Users online (1,869)