Skip to content

Commit

Permalink
Add tuples() to convert stream to [key, value] tuples (#147)
Browse files Browse the repository at this point in the history
  • Loading branch information
sanmai authored Jun 15, 2024
1 parent e1e4a2b commit 05a57f5
Show file tree
Hide file tree
Showing 3 changed files with 144 additions and 0 deletions.
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -123,6 +123,7 @@ All entry points always return an instance of the pipeline.
| `fold()` | Reduces input values to a single value. Defaults to summation. Requires an initial value. | `array_reduce`, `Aggregate`, `Sum` |
| `reduce()` | Alias to `fold()` with a reversed order of arguments. | `array_reduce` |
| `flip()` | Swaps keys and values. | `array_flip` |
| `tuples()` | Converts stream to [key, value] tuples. | |
| `max()` | Finds the highest value. | `max` |
| `min()` | Finds the lowest value. | `min` |
| `count()` | Counts values. Eagerly executed.| `array_count` |
Expand Down
34 changes: 34 additions & 0 deletions src/Standard.php
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@
use function min;
use function mt_getrandmax;
use function mt_rand;
use function array_keys;

/**
* Concrete pipeline with sensible default callbacks.
Expand Down Expand Up @@ -1053,6 +1054,39 @@ private static function flipKeysAndValues(iterable $previous): iterable
}
}

/**
* @return $this
*/
public function tuples()
{
if ($this->empty()) {
// No-op: null.
return $this;

Check warning on line 1064 in src/Standard.php

View workflow job for this annotation

GitHub Actions / Static Analysis and Validation

Escaped Mutant for Mutator "This": --- Original +++ New @@ @@ public function tuples() { if ($this->empty()) { - // No-op: null. - return $this; + return null; } if (is_array($this->pipeline)) { $this->pipeline = array_map(fn($key, $value) => [$key, $value], array_keys($this->pipeline), $this->pipeline);
}

if (is_array($this->pipeline)) {
$this->pipeline = array_map(
fn($key, $value) => [$key, $value],
array_keys($this->pipeline),
$this->pipeline
);

return $this;

Check warning on line 1074 in src/Standard.php

View workflow job for this annotation

GitHub Actions / Static Analysis and Validation

Escaped Mutant for Mutator "This": --- Original +++ New @@ @@ } if (is_array($this->pipeline)) { $this->pipeline = array_map(fn($key, $value) => [$key, $value], array_keys($this->pipeline), $this->pipeline); - return $this; + return null; } $this->pipeline = self::toTuples($this->pipeline); return $this;
}


$this->pipeline = self::toTuples($this->pipeline);

return $this;

Check warning on line 1080 in src/Standard.php

View workflow job for this annotation

GitHub Actions / Static Analysis and Validation

Escaped Mutant for Mutator "This": --- Original +++ New @@ @@ return $this; } $this->pipeline = self::toTuples($this->pipeline); - return $this; + return null; } private static function toTuples(iterable $previous) : iterable {
}

private static function toTuples(iterable $previous): iterable
{
foreach ($previous as $key => $value) {
yield [$key, $value];
}
}

private function feedRunningVariance(Helper\RunningVariance $variance, ?callable $castFunc): self
{
if (null === $castFunc) {
Expand Down
109 changes: 109 additions & 0 deletions tests/TuplesTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
<?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 ArrayIterator;
use PHPUnit\Framework\TestCase;

use Pipeline\Standard;
use IteratorIterator;

use function Pipeline\fromArray;
use function round;
use function sqrt;
use function Pipeline\take;
use function Pipeline\map;

/**
* @covers \Pipeline\Standard
*
* @internal
*/
final class TuplesTest extends TestCase
{
public static function provideArrays(): iterable
{
yield 'empty_array' => [[], []];
yield 'basic_key_values' => [['a' => 1, 'b' => 2, 'c' => 3], [['a', 1], ['b', 2], ['c', 3]]];
yield 'numeric_keys' => [[10, 20, 30], [[0, 10], [1, 20], [2, 30]]];

yield 'mixed_keys_values' => [
['name' => 'Alice', 1 => 'Bob'],
[['name', 'Alice'], [1, 'Bob']],
];

yield 'null_values' => [['x' => null, 'y' => null], [['x', null], ['y', null]]];

yield 'empty_string_key' => [['' => 'value'], [['', 'value']]];

yield 'nested_arrays' => [['outer' => ['inner1' => 'value1', 'inner2' => 'value2']], [['outer', ['inner1' => 'value1', 'inner2' => 'value2']]]];
}

public static function provideIterables(): iterable
{
foreach (self::provideArrays() as $name => $item) {
yield $item;

$iteratorItem = $item;
$iteratorItem[0] = new ArrayIterator($iteratorItem[0]);

yield "$name(ArrayIterator)" => $iteratorItem;

$iteratorItem = $item;
$iteratorItem[0] = new IteratorIterator(new ArrayIterator($iteratorItem[0]));

yield "$name(IteratorIterator)" => $iteratorItem;

$iteratorItem = $item;
$iteratorItem[0] = fromArray($iteratorItem[0]);

yield "$name(Pipeline)" => $iteratorItem;
}

yield 'generator' => [map(function () {
yield '1' => 2;
yield '2' => 3;
}), [['1', 2], ['2', 3]]];
}

/**
* @dataProvider provideIterables
*/
public function testTuples(iterable $input, array $expected, bool $preserve_keys = false): void
{
$pipeline = take($input);

$pipeline->tuples();

$this->assertSame(
$expected,
$pipeline->toArray($preserve_keys)
);
}

public function testNoop(): void
{
$pipeline = new Standard();

$pipeline->tuples();

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

0 comments on commit 05a57f5

Please sign in to comment.