Sort Array in Power Automate, Using Custom Code Connector

As I play around with leveraging code in custom connectors more and more, I just love the possibilities it offers.

One of the original posts I saw was from Alex Shlega where he gives an example sorting an array. Wow this is great! But what if my array is not an array of just string values? What if it has numbers, or complex values, or nulls, etc.?

So I extended his example a bit using custom sorting logic, and added the ability to choose your desired sort order.

Sort Array w/Custom Code Connector

Let’s see how that works.

(Please see my other posts where I discuss a few more details on using the custom connector UI and where to apply the YAML and C# script code when building the Regular Expression custom action and add some enhancements.)

Action Definition

Here’s what our custom action can do:

swagger: '2.0'
info: {title: SteelCut Bytes Actions, description: SteelCut Bytes Power Automate Actions,
  version: '1.0'}
host: flow.steelcutbytes.com
basePath: /
schemes: [https]
consumes: []
produces: []
paths:
  /SortArray:
    post:
      responses:
        default:
          description: default
          schema:
            type: array
            items: {}
            description: Sorted array
            title: Sorted Array
      summary: Sort array
      operationId: SortArray
      description: Sorts the array values using both String and Numeric comparison.
      parameters:
      - name: value
        in: body
        required: true
        schema:
          type: object
          properties:
            items:
              type: array
              items: {}
              description: Unsorted chaotic array of values
              title: Chaotic Array
            sort:
              title: Sort Order
              type: string
              enum: [Ascending, Descending, Reverse]
              default: Ascending
          required: [items, sort]
definitions: {}
parameters: {}
responses: {}
securityDefinitions: {}
security: []
tags: []

Normally, you want to be as specific as possible in the types used in the YAML definition. But, since we are allowing an array of multiple data types (string, numbers, null, objects, etc.) it pays to be vague in this case.

Secret sauce:

Declaring both our input and output array items without a type (items: {}) allows both our action and code to receive our array of varying data types.

Code

Here’s the C# code for the sorting logic:

public class Script : ScriptBase
{
    public override async Task<HttpResponseMessage> ExecuteAsync()
    {
        switch (this.Context.OperationId)
        {
            case "SortArray":
                return await this.HandleSortArray().ConfigureAwait(false);
        }

        var response = new HttpResponseMessage(HttpStatusCode.BadRequest);
        response.Content = CreateJsonContent($"Unknown operation ID '{this.Context.OperationId}'");
        return response;
    }

    private async Task<HttpResponseMessage> HandleSortArray()
    {
        var contentAsString = await this.Context.Request.Content.ReadAsStringAsync().ConfigureAwait(false);
        var contentAsJson = JObject.Parse(contentAsString);

        var stringJArray = (JArray)contentAsJson["items"];
        var sortOrder = (string)contentAsJson["sort"];

        var objectList = stringJArray.ToObject<List<Object>>();

        switch (sortOrder)
        {
            case "Ascending":
            case "Descending":
                objectList.Sort((x, y) =>
                {
                    var strX = (x == null ? null : x.ToString());
                    var strY = (y == null ? null : y.ToString());

                    decimal decX, decY;
                    if (decimal.TryParse(strX, out decX) && decimal.TryParse(strY, out decY))
                        return (decX > decY) ? 1 : (decX < decY) ? -1 : 0;
                    else
                        return StringComparer.Ordinal.Compare(strX, strY);
                });
                break;
        }

        if (sortOrder != "Ascending")
            objectList.Reverse();

        var result = JArray.FromObject(objectList);

        var response = new HttpResponseMessage(HttpStatusCode.OK);
        response.Content = CreateJsonContent(result.ToString());
        return response;
    }
}

The updates I’ve made to Alex Shlega’s example are highlighted in the code above. I’ll quickly explain those.

The first thing I do is make sure the JSON is converted to an array of objects and not strings.

var objectList = stringJArray.ToObject<List<Object>>();

This ensures that the types of numbers and other non-string data are preserved so that the sorting logic will distinguish them correctly. This comes in handy when sorting numbers in logical numeric order instead of string order, i.e. 0, 1, 2, 10 instead of "0", "1", "10", "2", and when handling null values.

Next I handle the sort logic, using the .NET Enumerable.Sort(...) extension method.

objectList.Sort((x, y) =>
{
  var strX = (x == null ? null : x.ToString());
  var strY = (y == null ? null : y.ToString());

  decimal decX, decY;
  if (decimal.TryParse(strX, out decX) && decimal.TryParse(strY, out decY))
    return (decX > decY) ? 1 : (decX < decY) ? -1 : 0;
  else
    return StringComparer.Ordinal.Compare(strX, strY);
});

To handle both integer and float number types, I check if the values are decimal using TryParse(...), and when true, I sort according to numeric logic.

If not numeric, then I treat all other types as a string (or null) and sort according to string sorting logic using StringComparer.Ordinal.Compare(...).

Here’s the output of the enhanced sort logic:

Unsorted input array -> Sorted output array

Simple as that!

But … it can be better!

This is definitely just a quick and easy sort. My main focus was on handling numbers correctly, empty strings, and null values.

When showing this to one of my brilliant co-workers (Reza Dorrani, thank you!) he suggested an enhancement to handle more complex data type scenarios, such as sorting objects by a specific property value.

This is on my to-do and will be the source of a future post.

Happy coding!


Follow My Blog

Get new content delivered directly to your inbox.

Author: Joey

I develop modern solutions leveraging the Microsoft cloud technologies: Power Platform and SharePoint Online, with a focus on process automation. I got my start writing code professionally beginning with Microsoft VB6, but really fell in love with code (and the art of it) with Microsoft .NET Framework version 1.0. I'm also a fan of Superman, so don't be surprised if references creep in. Up, Up, and Away!

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

%d bloggers like this: