Wicked Smart Data
LearnArticlesAbout
Sign InSign Up
LearnArticlesAboutContact
Sign InSign Up
Wicked Smart Data

The go-to platform for professionals who want to master data, automation, and AI — from Excel fundamentals to cutting-edge machine learning.

Platform

  • Learning Paths
  • Articles
  • About
  • Contact

Connect

  • Contact Us
  • RSS Feed

© 2026 Wicked Smart Data. All rights reserved.

Privacy PolicyTerms of Service
All Articles
Transforming and Mapping Data with Power Automate's Compose, Select, and Filter Array Actions

Transforming and Mapping Data with Power Automate's Compose, Select, and Filter Array Actions

Power Automate🌱 Foundation15 min readJun 24, 2026Updated Jun 24, 2026
Table of Contents
  • Introduction
  • Prerequisites
  • Understanding Arrays: The Data Structure Everything Runs Through
  • The Compose Action: Your Expression Scratchpad
  • Why Compose Exists
  • Using Compose in Practice
  • The Select Action: Reshaping Every Row in an Array
  • Anatomy of the Select Action
  • Setting Up a Select Action
  • Transforming Values, Not Just Renaming Them
  • What the Output Looks Like
  • The Filter Array Action: Keeping Only What You Need

Transforming and Mapping Data with Power Automate's Compose, Select, and Filter Array Actions

Introduction

Imagine you're pulling customer orders from a REST API. The API sends back a massive JSON object with 40 fields per order — customer IDs, internal pricing codes, warehouse flags, timestamps in UTC, raw tax calculations, and a dozen other fields your downstream system doesn't care about. All you need are six clean fields in a specific format, and only the orders that haven't shipped yet. Without the right tools, you'd be writing a separate flow action for every single field, stacking conditions until your flow looks like a plate of spaghetti.

This is exactly the problem that Compose, Select, and Filter Array were built to solve. These three actions are Power Automate's core data transformation toolkit. They let you reshape, remap, and reduce arrays of data before you send them anywhere — to SharePoint, to Excel, to an approval workflow, or back to another API. Together they turn messy, over-stuffed data into exactly the structure your process needs.

By the end of this lesson, you'll be able to take a raw array of records and reshape it into a clean, purposeful dataset using real expressions — not just drag-and-drop guessing. You'll understand how data flows through each action and why it's shaped the way it is.

What you'll learn:

  • What arrays are and why data transformation matters in automation
  • How to use Compose to store intermediate values and build reusable expressions
  • How to use Select to map an array into a new shape (like SQL's SELECT clause)
  • How to use Filter Array to reduce an array based on conditions
  • How to chain all three actions together in a realistic business scenario

Prerequisites

  • You have a Power Automate account (Microsoft 365 or a free trial at make.powerautomate.com)
  • You've built at least one simple flow — you know what a trigger and an action are
  • You're comfortable seeing JSON — you don't need to write it from scratch, but you shouldn't panic when you see curly braces

Understanding Arrays: The Data Structure Everything Runs Through

Before we touch any actions, let's get the mental model right. An array is simply a list of items. In Power Automate's world, that list usually contains objects — records with multiple fields each. Think of it like a spreadsheet: the array is the table, and each item in the array is one row.

Here's what a typical array looks like when Power Automate receives it from an API or a data source:

[
  {
    "order_id": "ORD-1041",
    "customer_name": "Priya Sharma",
    "status": "pending",
    "total_amount": 142.50,
    "internal_warehouse_code": "WH-7",
    "created_date": "2024-03-15T08:22:00Z"
  },
  {
    "order_id": "ORD-1042",
    "customer_name": "Marcus Webb",
    "status": "shipped",
    "total_amount": 89.00,
    "internal_warehouse_code": "WH-3",
    "created_date": "2024-03-15T09:45:00Z"
  },
  {
    "order_id": "ORD-1043",
    "customer_name": "Leila Okonkwo",
    "status": "pending",
    "total_amount": 310.00,
    "internal_warehouse_code": "WH-7",
    "created_date": "2024-03-15T11:00:00Z"
  }
]

Three orders, six fields each. The challenge: you only want the pending orders, and your reporting system only needs order_id, customer_name, and total_amount. Everything else is noise. That's exactly what we'll build in this lesson.

Why not just use "Apply to Each"? You could loop through every item and manually build a new object inside an Apply to Each block. But that approach creates extra actions, makes your flow harder to read, and is significantly slower on large datasets. Select and Filter Array are purpose-built for transformation — they do the work in a single action.


The Compose Action: Your Expression Scratchpad

The Compose action is the simplest of the three, and that simplicity is what makes it powerful. It takes whatever you put into its Inputs field — a value, an expression, a piece of text, an entire object — and stores it so you can reference it later in your flow using the outputs('Compose') dynamic value.

Think of Compose as a sticky note you write at the top of your desk. You calculate something once, write it down, and then refer to that note as many times as you need without recalculating it.

Why Compose Exists

Power Automate doesn't have a native "variable assignment" inside every expression. If you need to use the same computed value — say, today's date formatted a specific way — in five different places, you'd normally have to rewrite that expression five times. With Compose, you write it once.

Using Compose in Practice

Let's say you want to capture today's date in a readable format to use later in email subjects and file names. Here's how you'd set that up:

  1. Add a new step and search for "Compose" — it lives under the Data Operation category.
  2. Click into the Inputs field.
  3. Switch to Expression mode by clicking the "Expression" tab in the dynamic content panel.
  4. Enter this expression:
formatDateTime(utcNow(), 'yyyy-MM-dd')
  1. Click OK.

Now anywhere downstream in your flow, when you add dynamic content, you can select Outputs from this Compose action and it will carry that formatted date string.

You can also use Compose to construct a complete JSON object that you'll pass to another action:

{
  "report_title": "Daily Pending Orders",
  "generated_on": "2024-03-15",
  "generated_by": "Power Automate"
}

Just type or paste that directly into the Inputs field. Compose will store it as-is.

Tip: Name your Compose actions descriptively. Instead of the default "Compose," rename it to something like "Compose — Formatted Today's Date" or "Compose — Report Metadata." When you have six Compose actions in a flow, the default names become impossible to navigate.


The Select Action: Reshaping Every Row in an Array

If Compose is a sticky note, Select is a cookie cutter. You give it an array, define the shape you want each item to come out as, and it applies that shape to every single item. The result is a brand-new array with the same number of rows, but only the fields you chose — renamed and restructured however you like.

This is the equivalent of SELECT order_id, customer_name, total_amount FROM orders in SQL. You're not filtering rows; you're choosing and renaming columns.

Anatomy of the Select Action

The Select action has two inputs:

  • From: The array you're transforming. This is the input array — in our case, the full orders array from the API.
  • Map: A key-value grid where the key is the name you want in the output object, and the value is the expression that produces the data for that field.

Setting Up a Select Action

Add a new step and search for "Select" (also under Data Operation). You'll see two fields: From and Map.

Click into From and select your array — for our scenario, this is the dynamic value representing the full list of orders returned by the API call.

Now for the Map section, you'll see a small grid with a left column (key/name) and a right column (value). Let's build our three-field output.

Row 1:

  • Key: order_id
  • Value: Click into the right column and select the expression tab, then enter item()['order_id']

Row 2:

  • Key: customer_name
  • Value: item()['customer_name']

Row 3:

  • Key: order_total
  • Value: item()['total_amount']

Notice that third row — we renamed total_amount to order_total. That's intentional. The key column is your output name, and you control it completely.

What is item()? Inside a Select action's Map section, item() refers to the current item being processed — the equivalent of "this row" as Select loops through the array. You access its fields using bracket notation: item()['field_name'].

Transforming Values, Not Just Renaming Them

Select isn't just a rename tool — you can apply expressions to transform the values themselves. Want the total formatted as currency? Use:

formatNumber(item()['total_amount'], 'C2', 'en-US')

Want the customer name in uppercase?

toUpper(item()['customer_name'])

Want to concatenate a label onto the order ID?

concat('Order #', item()['order_id'])

The Map section accepts any valid Power Automate expression in the value column. This is where Select earns its keep — you're not just selecting fields, you're shaping data.

What the Output Looks Like

After running Select on our sample array, the output would be a new array like this:

[
  {
    "order_id": "ORD-1041",
    "customer_name": "Priya Sharma",
    "order_total": 142.50
  },
  {
    "order_id": "ORD-1042",
    "customer_name": "Marcus Webb",
    "order_total": 89.00
  },
  {
    "order_id": "ORD-1043",
    "customer_name": "Leila Okonkwo",
    "order_total": 310.00
  }
]

Three rows, three fields, clean and simple. All three items made it through because Select doesn't filter — it only transforms.


The Filter Array Action: Keeping Only What You Need

Now we tackle the filtering problem. Filter Array takes an array and applies a condition to each item. Items that meet the condition stay; items that don't are removed. The shape of each item doesn't change — that's Select's job. Filter Array purely decides which rows survive.

Think of it as a bouncer at a club door. Every item in your array walks up to the door. The bouncer checks the condition. Pass? You're in. Fail? You're not on the list.

Two Modes: Basic and Advanced

Filter Array offers two ways to define your condition:

Basic mode gives you a simple three-part interface: left value, comparison operator (equals, does not equal, greater than, etc.), and right value. This works for simple, single-condition filters.

Advanced mode (click "Edit in advanced mode") lets you write a full logical expression using Power Automate's formula language. This is what you'll use for anything beyond a single equals comparison.

Setting Up a Basic Filter

Add a Filter Array action. In the From field, select your input array.

For a basic filter to keep only orders where status equals "pending":

  • Left value: Click in the field, switch to Expression, and enter item()['status']
  • Operator: Select is equal to
  • Right value: Type pending (no quotes needed in the basic mode value field)

That's it. Run the flow and only the pending orders pass through.

Advanced Mode for Complex Conditions

What if you want orders that are pending AND have a total over $100? Basic mode can't handle AND logic. Switch to advanced mode and write:

@and(
  equals(item()['status'], 'pending'),
  greater(item()['total_amount'], 100)
)

The @ prefix tells Power Automate this is an expression. The and() function takes two conditions, both of which must be true for the item to pass.

Warning: In advanced mode, string values in expressions must use single quotes, not double quotes. Writing equals(item()['status'], "pending") will fail. Use 'pending' instead.

You can also use or() for either-or conditions:

@or(
  equals(item()['status'], 'pending'),
  equals(item()['status'], 'processing')
)

What the Output Looks Like After Filtering

Applying the basic status filter to our sample array, the output would be:

[
  {
    "order_id": "ORD-1041",
    "customer_name": "Priya Sharma",
    "status": "pending",
    "total_amount": 142.50,
    "internal_warehouse_code": "WH-7",
    "created_date": "2024-03-15T08:22:00Z"
  },
  {
    "order_id": "ORD-1043",
    "customer_name": "Leila Okonkwo",
    "status": "pending",
    "total_amount": 310.00,
    "internal_warehouse_code": "WH-7",
    "created_date": "2024-03-15T11:00:00Z"
  }
]

Marcus Webb's shipped order is gone. The remaining items still have all their original fields — Filter Array didn't reshape anything. That's why order matters when you chain these two actions together.


Chaining It All Together: Filter Then Select

Here's the key insight about using these actions together: order matters. Should you filter first or select first?

Filter first, then Select. Here's why: Filter Array uses item()['field_name'] to evaluate conditions. If you run Select first and strip out the status field, your Filter Array action can no longer access it to evaluate the condition. You'd be trying to check a field that no longer exists.

The correct chain for our scenario:

  1. HTTP action — Get orders from the API (returns the raw 40-field array)
  2. Filter Array — Keep only items where status equals pending
  3. Select — Map filtered results to just order_id, customer_name, order_total
  4. Downstream action — Send the clean array to SharePoint, email, or wherever it needs to go

This is clean, efficient, and readable. Anyone opening your flow can immediately understand what's happening at each stage.

Tip: Use a Compose action between steps to inspect intermediate state during development. Add a Compose action after Filter Array and set its input to the Filter Array output. Run the flow manually, then open the run history and expand that Compose action to see exactly what the array looks like at that point. Delete the Compose action once you're done debugging.


Hands-On Exercise

Build this flow from start to finish. It uses a manual trigger so you don't need any external system to practice.

Goal: Start with a hardcoded array of employee records. Filter to only active employees in the Engineering department. Then map them to a simplified output with just their name, department, and a formatted employee label.

Step 1: Create the Flow

Go to My Flows → New Flow → Instant cloud flow → Manually trigger a flow.

Step 2: Add a Compose Action for Sample Data

Add a Compose step. In the Inputs field, paste this array directly:

[
  {"emp_id": "E101", "full_name": "Jordan Kim", "department": "Engineering", "status": "active", "salary": 95000},
  {"emp_id": "E102", "full_name": "Sandra Osei", "department": "Marketing", "status": "active", "salary": 72000},
  {"emp_id": "E103", "full_name": "Tobias Reyes", "department": "Engineering", "status": "inactive", "salary": 88000},
  {"emp_id": "E104", "full_name": "Anika Patel", "department": "Engineering", "status": "active", "salary": 102000}
]

Rename this step to "Compose — Sample Employee Data".

Step 3: Add a Filter Array Action

Add a Filter Array step. Set the From field to the outputs of your Compose step (select it from dynamic content).

Switch to advanced mode and enter:

@and(
  equals(item()['status'], 'active'),
  equals(item()['department'], 'Engineering')
)

This keeps only Jordan Kim and Anika Patel.

Step 4: Add a Select Action

Add a Select step. Set From to the output of the Filter Array step.

In the Map section, add these three rows:

Key Value (Expression)
employee_label concat('EMP: ', item()['full_name'])
department item()['department']
status toUpper(item()['status'])

Step 5: Add a Final Compose to See the Result

Add one more Compose step and set its input to the output of the Select action. This lets you inspect the final array in the run history.

Step 6: Save and Run

Click Save, then click Test → Manually → Run flow. Once it completes, click on the run to open the run history, expand the final Compose action, and inspect the outputs. You should see:

[
  {
    "employee_label": "EMP: Jordan Kim",
    "department": "Engineering",
    "status": "ACTIVE"
  },
  {
    "employee_label": "EMP: Anika Patel",
    "department": "Engineering",
    "status": "ACTIVE"
  }
]

Common Mistakes & Troubleshooting

"My Select output is an array of arrays, not an array of objects." This happens when the From field of Select is set to the entire output of an action instead of the array body within it. For example, if an HTTP action returns a response with a body property containing your array, you need to reference body specifically, not the whole HTTP response. Use body('HTTP_Action_Name') in an expression.

"Filter Array is keeping everything / filtering everything out." Check your field name capitalization. item()['Status'] is different from item()['status']. JSON field names are case-sensitive. Open your run history, find the trigger or input action, and look at the exact field names in the raw data.

"My expression in advanced Filter mode throws an error about invalid JSON." Make sure you're using single quotes for string literals, not double quotes. Also ensure you haven't accidentally left the @ sign out — without it, the field is treated as a plain string, not an expression.

"I renamed my Compose action and now downstream references are broken." When you rename an action, any dynamic content references that were already placed in later steps may break because they still reference the old internal name. After renaming, manually re-select the dynamic content outputs in the downstream steps to update the references.

"Select is outputting null for some fields." The field name in your item()['field_name'] expression doesn't match what's actually in the data. Again, case matters. Use run history to inspect the raw input to Select and copy the field names exactly as they appear.


Summary & Next Steps

You've now got the three foundational data transformation actions in your Power Automate toolkit. Let's recap what each one does:

  • Compose stores a computed value or structure for reuse — your scratchpad for expressions and intermediate data
  • Select maps an entire array to a new shape, transforming and renaming fields in every row without filtering
  • Filter Array reduces an array by removing rows that don't meet your conditions, without changing the shape of remaining rows

The pattern that makes these powerful is combining them in the right order: filter first to remove unwanted rows, then select to reshape what remains. This approach keeps your conditions clear (they can reference all original fields) and keeps your data clean at the end.

Where to go next:

  • Parse JSON action: When your array comes from an HTTP call or a variable, Parse JSON generates a schema that makes dynamic content from that array available without writing manual item()['field_name'] expressions everywhere. It's the natural companion to these three actions.
  • Apply to Each with conditions: Once you have a clean, filtered array, sometimes you need to act on each item individually — sending an email per record, creating a SharePoint item per row. Apply to Each is designed for that scenario.
  • Join action: After transforming your array, the Join action lets you collapse it into a single delimited string — useful for building email body lists or CSV-style outputs.

Master these three actions and you'll handle the data transformation layer of almost any flow without fighting with the tool. The goal is always the same: get the right data, in the right shape, to the right destination — and now you know exactly how to do that.

Learning Path: Flow Automation Basics

Previous

Orchestrating Child Flows and Scoped Execution in Power Automate for Scalable, Reusable Automation Architecture

Related Articles

Power Automate🔥 Expert

Orchestrating Child Flows and Scoped Execution in Power Automate for Scalable, Reusable Automation Architecture

32 min
Power Automate⚡ Practitioner

Advanced Power Automate: Custom Connectors and HTTP Actions for Production Integration

12 min
Power Automate🌱 Foundation

Power Automate Best Practices: Master Flow Naming, Testing, and Monitoring

13 min

On this page

  • Introduction
  • Prerequisites
  • Understanding Arrays: The Data Structure Everything Runs Through
  • The Compose Action: Your Expression Scratchpad
  • Why Compose Exists
  • Using Compose in Practice
  • The Select Action: Reshaping Every Row in an Array
  • Anatomy of the Select Action
  • Setting Up a Select Action
  • Transforming Values, Not Just Renaming Them
Two Modes: Basic and Advanced
  • Setting Up a Basic Filter
  • Advanced Mode for Complex Conditions
  • What the Output Looks Like After Filtering
  • Chaining It All Together: Filter Then Select
  • Hands-On Exercise
  • Step 1: Create the Flow
  • Step 2: Add a Compose Action for Sample Data
  • Step 3: Add a Filter Array Action
  • Step 4: Add a Select Action
  • Step 5: Add a Final Compose to See the Result
  • Step 6: Save and Run
  • Common Mistakes & Troubleshooting
  • Summary & Next Steps
  • What the Output Looks Like
  • The Filter Array Action: Keeping Only What You Need
  • Two Modes: Basic and Advanced
  • Setting Up a Basic Filter
  • Advanced Mode for Complex Conditions
  • What the Output Looks Like After Filtering
  • Chaining It All Together: Filter Then Select
  • Hands-On Exercise
  • Step 1: Create the Flow
  • Step 2: Add a Compose Action for Sample Data
  • Step 3: Add a Filter Array Action
  • Step 4: Add a Select Action
  • Step 5: Add a Final Compose to See the Result
  • Step 6: Save and Run
  • Common Mistakes & Troubleshooting
  • Summary & Next Steps