How to Unzip an Array

How to unzip an Array?

Use transpose:

> zipped = x.zip(y)
=> [[1, 4], [2, 5], [3, 6]]
> x2, y2 = zipped.transpose
> x2
=> [1, 2, 3]
> y2
=> [4, 5, 6]

Unzip a NumPy array

You can only ever unpack the first dimension of an array, but the dimension you want to unpack is the second one. This means in your case, you can do:

x10, x11 = br.T

Be aware that x10 and x11 will be a view into br! This means if you change any of the values in any of these arrays, you will change the other variables too.

If your array has more than 2D dimensions (extra [ and ]), check the shape of your array using

br.shape

and if you see superfluous empty dimensions (1), remove them using

br = br.squeeze()

Type of zip and unzip array functions?

I got a solution for unzip that does what you want.

function unzip<
T extends [...{ [K in keyof S]: S[K] }][], S extends any[]
>(arr: [...T]): T[0] extends infer A
? { [K in keyof A]: T[number][K & keyof T[number]][] }
: never
{
const maxLength = Math.max(...arr.map((x) => x.length));

return arr.reduce(
(acc: any, val) => {
val.forEach((v, i) => acc[i].push(v));

return acc;
},
range(maxLength).map(() => [])
);
}

Let's see if it works:

const a = unzip([[1, "a"], [2, "b"], [3, "c"]])
// ^? [number[], string[]]

const b = unzip([[1, "a", new Date()], [2, "b", new Date()], [3, "c", new Date()]] )
// ^? [number[], string[], Date[]]

const c = unzip([[1, "a"], [2, "b"], [3, undefined]])
// ^? [number[], (string | undefined)[]]

Playground


Here is an alternative solution that is fully compatible with the solution above. But for array literals, this will produce more accurate return types.

type ValidContent =
| null
| string
| number
| boolean
| Array<JSON>
| Date
| undefined
| {
[prop: string]: ValidContent
}

type UnzipReturn<T extends any[]> = T[0] extends infer A
? {
[K in keyof A]: [...{
[K2 in keyof T]: T[K2][K & keyof T[K2]]
}]
}
: never

function unzip<
T extends [...{[K in keyof S]: S[K]}][], S extends ValidContent[]
>(arr: [...T]): UnzipReturn<T> {
const maxLength = Math.max(...arr.map((x) => x.length));

return arr.reduce(
(acc: any, val) => {
val.forEach((v, i) => acc[i].push(v));

return acc;
},
range(maxLength).map(() => [])
);
}
const a = unzip([[1, "a"], [2, "b"], [3, "c"]])
// ^? [[1, 2, 3], ["a", "b", "c"]]

const b = unzip([[1, "a", new Date()], [2, "b", new Date()], [3, "c", new Date()]] )
// ^? [[1, 2, 3], ["a", "b", "c"], [Date, Date, Date]]

const c = unzip([[1, "a"], [2, "b"], [3, undefined]])
// ^? [[1, 2, 3], ["a", "b", undefined]]

const d = unzip([[1, "a"], [2, "b"], [3, "c"]] as [number, string][])
// ^? [number[], string[]]

Playground

Transpose/Unzip Function (inverse of zip)?

zip is its own inverse! Provided you use the special * operator.

>>> zip(*[('a', 1), ('b', 2), ('c', 3), ('d', 4)])
[('a', 'b', 'c', 'd'), (1, 2, 3, 4)]

The way this works is by calling zip with the arguments:

zip(('a', 1), ('b', 2), ('c', 3), ('d', 4))

… except the arguments are passed to zip directly (after being converted to a tuple), so there's no need to worry about the number of arguments getting too big.

unzip list of tuples into numpy arrays

Your list of tuples can be converted into a 2-d numpy array by calling np.array. This can then be transposed and then unpacked along the first dimension using tuple assignment:

b, c = np.array(a).T

Here this gives:

>>> import numpy as np
>>> a = [(1,2), (3,4)]
>>> b, c = np.array(a).T # or: np.array(a).transpose()
>>> b
array([1, 3])
>>> c
array([2, 4])

Caveat: you will have a temporary array with the same number of elements as a, so it might be less memory-efficient than your original solution, particularly if you are unpacking into a larger number of 1d arrays.

Unzip an array of tuples in julia

For larger arrays use @ivirshup's solution below.

For smaller arrays, you can use zip and splitting.

You can achieve the same thing in Julia by using the zip() function (docs here). zip() expects many tuples to work with so you have to use the splatting operator ... to supply your arguments. Also in Julia you have to use the collect() function to then transform your iterables into an array (if you want to).

Here are these functions in action:

arr = [(1,2), (3,4), (5,6)]

# wtihout splatting
collect(zip((1,2), (3,4), (5,6)))

# Output is a vector of arrays:
> ((1,3,5), (2,4,6))

# same results with splatting
collect(zip(arr...))
> ((1,3,5), (2,4,6))

Unpacking an array in python

You could simply transpose it before unpacking:

x, y, z = data.T

Unpacking "unpacks" the first dimensions of an array and by transposing the your array the size-3 dimension will be the first dimension. That's why it didn't work with [x, y, z] = data1[:, 0:3] because that tried to unpack 1000 values into 3 variables.

How to unzip a list of tuples into individual lists?

Use zip(*list):

>>> l = [(1,2), (3,4), (8,9)]
>>> list(zip(*l))
[(1, 3, 8), (2, 4, 9)]

The zip() function pairs up the elements from all inputs, starting with the first values, then the second, etc. By using *l you apply all tuples in l as separate arguments to the zip() function, so zip() pairs up 1 with 3 with 8 first, then 2 with 4 and 9. Those happen to correspond nicely with the columns, or the transposition of l.

zip() produces tuples; if you must have mutable list objects, just map() the tuples to lists or use a list comprehension to produce a list of lists:

map(list, zip(*l))          # keep it a generator
[list(t) for t in zip(*l)] # consume the zip generator into a list of lists


Related Topics



Leave a reply



Submit