Skip to content

Commit

Permalink
Merge 03bde0f into d743b82
Browse files Browse the repository at this point in the history
  • Loading branch information
sanmai committed Mar 14, 2020
2 parents d743b82 + 03bde0f commit 0698fdd
Show file tree
Hide file tree
Showing 5 changed files with 202 additions and 2 deletions.
34 changes: 34 additions & 0 deletions src/Interfaces/ZipPipeline.php
@@ -0,0 +1,34 @@
<?php
/**
* Copyright 2017, 2018 Alexey Kopytko <alexey@kopytko.com>
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

declare(strict_types=1);

namespace Pipeline\Interfaces;

/**
* Interface definitions for the zipping pipeline.
*/
interface ZipPipeline
{
/**
* Performs a lazy zip operation on iterables, not unlike that of
* array_map with first argument set to null. Also known as transposition.
*
* @return $this
*/
public function zip(iterable ...$inputs);
}
51 changes: 49 additions & 2 deletions src/Principal.php
Expand Up @@ -22,7 +22,7 @@
/**
* Principal abstract pipeline with no defaults. Could be subclassed.
*/
abstract class Principal implements Interfaces\PrincipalPipeline
abstract class Principal implements Interfaces\PrincipalPipeline, Interfaces\ZipPipeline
{
/**
* Pre-primed pipeline.
Expand Down Expand Up @@ -76,7 +76,7 @@ public function map(callable $func)
return $this;
}

private static function apply(iterable $previous, callable $func): \Generator
private static function apply(iterable $previous, callable $func): iterable
{
foreach ($previous as $value) {
$result = $func($value);
Expand Down Expand Up @@ -178,4 +178,51 @@ public function reduce(callable $func, $initial)

return $initial;
}

public function zip(iterable ...$inputs): self
{
if (empty($this->pipeline)) {
$this->pipeline = \array_shift($inputs);
}

if ($inputs === []) {
return $this;
}

$this->map(static function ($item): array {
return [$item];
});

foreach (self::toIterators(...$inputs) as $iterator) {
$this->map(static function (array $current) use ($iterator) {
if ($iterator->valid()) {
$current[] = $iterator->current();
$iterator->next();
}

return $current;
});
}

return $this;
}

/** @return \Iterator[] */
private static function toIterators(iterable ...$inputs): array
{
return \array_map(static function (iterable $input): \Iterator {
while ($input instanceof \IteratorAggregate) {
$input = $input->getIterator();
}

if ($input instanceof \Iterator) {
return $input;
}

// IteratorAggregate and Iterator are out of picture, which leaves... an array

/** @var array $input */
return new \ArrayIterator($input);
}, $inputs);
}
}
8 changes: 8 additions & 0 deletions src/functions.php
Expand Up @@ -39,3 +39,11 @@ function fromArray(array $input): Standard
{
return new Standard($input);
}

function zip(iterable $base, iterable ...$inputs): Standard
{
$result = take($base);
$result->zip(...$inputs);

return $result;
}
18 changes: 18 additions & 0 deletions tests/FunctionsTest.php
Expand Up @@ -24,11 +24,13 @@
use function Pipeline\map;
use Pipeline\Standard;
use function Pipeline\take;
use function Pipeline\zip;

/**
* @covers \Pipeline\fromArray
* @covers \Pipeline\map
* @covers \Pipeline\take
* @covers \Pipeline\zip
*
* @internal
*/
Expand Down Expand Up @@ -84,4 +86,20 @@ public function testFromArray(): void
$this->assertInstanceOf(Standard::class, $pipeline);
$this->assertSame(\range(0, 100), $pipeline->toArray());
}

/**
* @covers \Pipeline\zip
*/
public function testZip(): void
{
$pipeline = zip([1, 2], [3, 4]);
$this->assertSame([[1, 3], [2, 4]], $pipeline->toArray());

$array = [[1, 2, 3], [4, 5, 6], [7, 8, 9]];

$pipeline = zip(...$array);
$this->assertInstanceOf(Standard::class, $pipeline);

$this->assertSame(\array_map(null, ...$array), $pipeline->toArray());
}
}
93 changes: 93 additions & 0 deletions tests/ZipTest.php
@@ -0,0 +1,93 @@
<?php
/**
* Copyright 2017, 2018 Alexey Kopytko <alexey@kopytko.com>
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

declare(strict_types=1);

namespace Tests\Pipeline;

use PHPUnit\Framework\TestCase;
use function Pipeline\fromArray;
use function Pipeline\map;
use Pipeline\Standard;

/**
* @covers \Pipeline\Principal
*
* @internal
*/
final class ZipTest extends TestCase
{
/**
* @covers \Pipeline\Principal::zip()
*/
public function testZipArray(): void
{
$pipeline = new Standard();

$pipeline->zip([1, 2], [3, 4]);
$this->assertSame([[1, 3], [2, 4]], $pipeline->toArray());

$array = [[1, 2, 3], [4, 5, 6], [7, 8, 9]];

$pipeline = new Standard();

$pipeline->zip(...$array);

$this->assertSame(\array_map(null, ...$array), $pipeline->toArray());
}

/**
* @covers \Pipeline\Principal::zip()
*/
public function testZipSelf(): void
{
$pipeline = fromArray([1, 2]);

$pipeline->zip(fromArray([3, 4]));

$this->assertSame([[1, 3], [2, 4]], $pipeline->toArray());
}

/**
* @covers \Pipeline\Principal::zip()
*/
public function testZipGenerator(): void
{
$pipeline = map(function () {
yield 1;
yield 2;
});

$pipeline->zip(map(function () {
yield 3;
yield 4;
}));

$this->assertSame([[1, 3], [2, 4]], $pipeline->toArray());
}

/**
* @covers \Pipeline\Principal::zip()
*/
public function testNoop(): void
{
$pipeline = new Standard();
$pipeline->zip([3, 4]);

$this->assertSame([3, 4], $pipeline->toArray());
}
}

0 comments on commit 0698fdd

Please sign in to comment.