Last active
June 10, 2018 20:06
-
-
Save castarco/722b60bd67cc8ae7880d4785b53819a9 to your computer and use it in GitHub Desktop.
PHP's array_zip
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?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