List.Zip Function (Power Query M)

If you have a few parallel lists and you want to pair up their items by position, like turning columns into rows, the List.Zip function is what you reach for. It takes a list of lists and lines them up like a zipper, so the first item of each list goes together, then the second, and so on.

In this article, I’ll show you how to use List.Zip to pair lists by position and build tables from them.

Syntax of List.Zip Function

List.Zip(lists as list) as list

where

  • lists (required, list). A list of lists. These are the lists you want to pair up by position, passed together inside one outer list.

Returns: a list of lists. Each inner list groups the items that sat at the same position across the input lists.

In plain terms, you hand it several lists wrapped in one outer list, and it gives you back the first items together, the second items together, and so on.

Example 1: Pair two lists by position

Say you have one list of regions and one list of sales numbers, and you want to pair each region with its sales figure.

List.Zip({{"North","South","East"},{120,90,75}})

Result: {{"North",120},{"South",90},{"East",75}}

Each region is paired with the sales number that sat at the same position in the second list.

Example 2: Pair three lists at once

You can zip more than two lists. Here you have SKUs, product names, and prices as three separate lists.

List.Zip({{"SKU-1","SKU-2","SKU-3"},{"Pen","Notebook","Eraser"},{2.5,4.0,1.25}})

Result: {{"SKU-1","Pen",2.5},{"SKU-2","Notebook",4.0},{"SKU-3","Eraser",1.25}}

Every inner list now holds one item from each of the three input lists, grouped by position.

Example 3: Lists of unequal length get padded with null

When the lists are not the same length, List.Zip pads the shorter ones with null so every group still has one slot per input list.

Here the day list has three items but the hours list only has two.

List.Zip({{"Mon","Tue","Wed"},{8,6}})

Result: {{"Mon",8},{"Tue",6},{"Wed",null}}

The third group gets null for the missing hours value because the second list ran out of items.

Example 4: Build a table from two column lists

The most common reason to use List.Zip is to turn parallel lists into a table. On its own the function gives you a nested list, so you wrap it in Table.FromRows to get real rows and columns.

Say you have a regions list and a sales list and you want a two-column table.

You want the regions in one column and the sales in another.

let
Source = Table.FromRows(List.Zip({{"North","South","East"},{120,90,75}}),{"Region","Sales"})
in
Source

List.Zip pairs the items into rows, and Table.FromRows turns those rows into a table with the column names you pass.

The result is a clean table:

RegionSales
North120
South90
East75

Each paired row from the zip becomes one row in the table.

Example 5: Pair keys with values into a table

The same pattern scales to more columns. Here you build a three-column product table from three parallel lists.

You have SKUs, product names, and prices, and you want them side by side.

let
Source = Table.FromRows(List.Zip({{"SKU-1","SKU-2","SKU-3"},{"Pen","Notebook","Eraser"},{2.5,4.0,1.25}}),{"SKU","Product","Price"})
in
Source

List.Zip groups the items at each position, then Table.FromRows lays them out under the three column names. From here you can keep building, for example stacking more tables with Table.Combine.

The result is a three-column table:

SKUProductPrice
SKU-1Pen2.5
SKU-2Notebook4
SKU-3Eraser1.25

Each SKU lines up with its product and price because all three sat at the same spot in their own list.

Things to keep in mind with List.Zip

  • It takes one argument, not several. Write List.Zip({{1,2},{3,4}}), not List.Zip({1,2},{3,4}). The lists you want to pair all go inside one outer list, and passing them as separate arguments throws an error.
  • The result stays nested. You get a list of lists back, not a table. To use it as rows and columns, feed it into Table.FromRows (Examples 4 and 5).
  • It pairs by position, not by value. The first items go together, then the second, and so on. If your lists are not in matching order, the pairs will be wrong even though no error appears. Reorder a list first with List.Sort if you need it.
  • Shorter lists are padded with null. When lengths differ, missing slots fill with null rather than dropping the row (Example 3). Clean or trim your lists first if you do not want stray null values.
  • To go the other direction, you do not use List.Zip. If you already have a table and want each column back as its own list, pull the columns out with Table.ToColumns. To build a table from whole-column lists instead of position-paired rows, use Table.FromColumns.
  • It reshapes lists, it does not change their items. If you also need to clean or convert the values as you pair them, run a List.Transform over each list first, then zip the cleaned lists.

Common questions about List.Zip

What is the difference between List.Zip and Table.FromColumns?

List.Zip pairs items by position into nested rows, so each inner list is one row across your inputs. Table.FromColumns treats each list as a whole column and stacks them side by side, with no pairing into rows.

How do I turn the zipped result into a table?

Wrap it in Table.FromRows and pass the column names, like Table.FromRows(List.Zip({{1,2},{3,4}}),{"Col1","Col2"}). The zip produces the rows and Table.FromRows gives them headers.

List of All Power Query Functions

Related Power Query Functions / Articles:

I am a huge fan of Microsoft Excel and love sharing my knowledge through articles and tutorials. I work as a business analyst and use Microsoft Excel extensively in my daily tasks. My aim is to help you unleash the full potential of Excel and become a data-slaying wizard yourself.