Skip to content

Instantly share code, notes, and snippets.

@castarco
Last active June 10, 2018 20:06
Show Gist options
  • Star 3 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save castarco/722b60bd67cc8ae7880d4785b53819a9 to your computer and use it in GitHub Desktop.
Save castarco/722b60bd67cc8ae7880d4785b53819a9 to your computer and use it in GitHub Desktop.
PHP's array_zip
<?php
declare(strict_types=1);
function array_zip(array ...$arrays): array
{
// Applied suggestion from reddit
// https://www.reddit.com/r/PHP/comments/76czco/php_equivalent_of_pythons_zip_function/doe5j86/
return \array_map(null, ...$arrays);
}
// Example usages:
//
// $tuples_array = array_zip([1,2,3]);
// $tuples_array === [ [1], [2], [3] ]
//
// $tuples_array = array_zip([1,2,3], [4,5,6]);
// $tuples_array === [ [1,4], [2,5], [3,6] ]
//
// $tuples_array = array_zip([1,2,3], [4,5]);
// $tuples_array === [ [1,4], [2,5], [3,null] ]
//
// $tuples_array = array_zip([1,2,3], [4,5,6], [7, 8, 9]);
// $tuples_array === [ [1,4,7], [2,5,8], [3,6,9] ]
////////////////////////////////////////////////////////////////////////////////
// Here you have a more useful construct, the same for iterators: //
// the aim is to use less memory in some cases //
////////////////////////////////////////////////////////////////////////////////
function iterable_zip(iterable ...$iterable_list): \Generator
{
/** @var \Iterator[] $_iterable_list */
$iterators = \array_map('iterable_to_iterator', $iterable_list);
while (contains_valid_iterator($iterators)) {
// WARNING: Be aware that this array_map call has side effects (on the iterator)!
yield \array_map(
function (\Iterator $iterator) {
if ($iterator->valid()) {
$v = $iterator->current();
$iterator->next();
return $v;
} else {
return null;
}
},
$iterators
);
}
}
function iterable_to_iterator(iterable $stream): \Iterator {
if ($stream instanceof \Iterator) {
return $stream;
} elseif ($stream instanceof \IteratorAggregate) {
return iterable_to_iterator($stream->getIterator());
} elseif (\is_array($stream)) {
return new \ArrayIterator($stream);
} else {
throw new \RuntimeException('Impossible state');
}
}
/**
* @param \Iterator[] $iterators
* @return bool
*/
function contains_valid_iterator(array $iterators): bool
{
return \array_reduce(
$iterators,
function (bool $carry, \Iterator $stream) {
return $carry || $stream->valid();
},
false
);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment