@@ -22,7 +22,8 @@ import .Base:
22
22
getindex, setindex!, get, iterate,
23
23
popfirst!, isdone, peek
24
24
25
- export enumerate, zip, rest, countfrom, take, drop, cycle, repeated, product, flatten, partition
25
+ export enumerate, zip, unzip, rest, countfrom, take, drop,
26
+ cycle, repeated, product, flatten, partition
26
27
27
28
tail_if_any (:: Tuple{} ) = ()
28
29
tail_if_any (x:: Tuple ) = tail (x)
@@ -390,6 +391,69 @@ _zip_iterator_eltype(::Type{Tuple{}}) = HasEltype()
390
391
391
392
reverse (z:: Zip ) = Zip (map (reverse, z. is))
392
393
394
+ # unzip
395
+
396
+ """
397
+ unzip(itrs) -> Vector{<:Vector}
398
+
399
+ The `unzip` function takes an iterator of iterators and returns a vector of
400
+ vectors such that the first vector contains the first element yielded by each
401
+ iterator, the second vector the second element yielded by each iterator, etc.
402
+ `unzip` is sort of an inverse to the `zip` operation, as the name suggests.
403
+ In particular, if we define
404
+
405
+ ≐(a, b) = collect(collect.(a)) == collect(collect.(b))
406
+
407
+ Then the following identities relating `zip` and `unzip` hold:
408
+
409
+ unzip(zip(itrs...)) ≐ itrs
410
+
411
+ zip(unzip(itrs)...) ≐ itrs
412
+
413
+ Note that `unzip` does not return an iterator: it always consumes all of
414
+ its argument and all of each iterator yielded by its argument. It is only
415
+ associated with iteration beacuse it is the inverse of `zip` which does
416
+ yield an iterator.
417
+
418
+ # Examples
419
+
420
+ ```jldoctest
421
+ julia> unzip(enumerate("Hello"))
422
+ 2-element Array{Array{T,1} where T,1}:
423
+ [1, 2, 3]
424
+ ['a', 'b', 'c']
425
+
426
+ julia> unzip([[1, 'a'], [2.5, 'z'], [0, 'x']])
427
+ 2-element Array{Array{T,1} where T,1}:
428
+ Real[1, 2.5, 0]
429
+ ['a', 'z', 'x']
430
+ ```
431
+ """
432
+ function unzip (itrs)
433
+ n = Base. haslength (itrs) ? length (itrs) : - 1
434
+ vecs = Vector[]
435
+ for itr in itrs
436
+ for (j, x) in enumerate (itr)
437
+ if length (vecs) < j
438
+ v = [x]
439
+ push! (vecs, v)
440
+ n ≥ 0 && sizehint! (v, n)
441
+ else
442
+ v = vecs[j]
443
+ if ! (x isa eltype (v))
444
+ T = Base. promote_typejoin (typeof (x), eltype (v))
445
+ v = vecs[j] = copyto! (similar (v, T), v)
446
+ n ≥ 0 && sizehint! (v, n)
447
+ end
448
+ push! (v, x)
449
+ end
450
+ end
451
+ length (first (vecs)) == length (last (vecs)) ||
452
+ throw (ArgumentError (" unzip called with uneven iterators" ))
453
+ end
454
+ return vecs
455
+ end
456
+
393
457
# filter
394
458
395
459
struct Filter{F,I}
0 commit comments