Skip to content

Commit

Permalink
refactor: Update Window operation in point free style. (#179)
Browse files Browse the repository at this point in the history
* refactor: Update Window operation in point free style.

* docs: Update Window operation documentation.

* fix: Fix SA return types.

* fix: Fix minor typo.

* tests: Add/update window operation tests.

* Autofix CS.
  • Loading branch information
drupol committed Aug 22, 2021
1 parent 6732261 commit e59b29b
Show file tree
Hide file tree
Showing 5 changed files with 66 additions and 137 deletions.
12 changes: 6 additions & 6 deletions docs/pages/api.rst
Expand Up @@ -2439,16 +2439,16 @@ window
Loop the collection yielding windows of data by adding a given number of items to the current item.
Initially the windows yielded will be smaller, until size ``1 + $size`` is reached.

Interface: `Windowable`_
.. tip:: To remove the window size constraint and have a dynamic window size, set the ``$size`` to ``-1``.

Signature: ``Collection::window(int $size): Collection;``
.. note:: When ``$size`` is equal to ``0``, the window will only contain the current element, wrapped in an array.

.. code-block:: php
Interface: `Windowable`_

$data = range('a', 'd');
Signature: ``Collection::window(int $size): Collection;``

Collection::fromIterable($data)
->window(2); // [['a'], ['a', 'b'], ['a', 'b', 'c'], ['b', 'c', 'd']]
.. literalinclude:: code/operations/window.php
:language: php

words
~~~~~
Expand Down
28 changes: 28 additions & 0 deletions docs/pages/code/operations/window.php
@@ -0,0 +1,28 @@
<?php

/**
* For the full copyright and license information, please view
* the LICENSE file that was distributed with this source code.
*/

declare(strict_types=1);

namespace App;

use loophp\collection\Collection;

include __DIR__ . '/../../../../vendor/autoload.php';

$data = range('a', 'e');

Collection::fromIterable($data)
->window(0); // [['a'], ['b'], ['c'], ['d'], ['e']]

Collection::fromIterable($data)
->window(1); // [['a'], ['a', 'b'], ['b', 'c'], ['c', 'd'], ['d', 'e']]

Collection::fromIterable($data)
->window(2); // [['a'], ['a', 'b'], ['a', 'b', 'c'], ['b', 'c', 'd'], ['c', 'd', 'e']]

Collection::fromIterable($data)
->window(-1); // [['a'], ['a', 'b'], ['a', 'b', 'c'], ['a', 'b', 'c', 'd'], ['a', 'b', 'c', 'd', 'e']]
122 changes: 14 additions & 108 deletions spec/loophp/collection/CollectionSpec.php
Expand Up @@ -4012,11 +4012,15 @@ public function it_can_when(): void

public function it_can_window(): void
{
$this::fromIterable(range('a', 'z'))
$this::fromIterable(['a' => 'A', 'b' => 'B', 'c' => 'C'])
->window(0)
->shouldIterateAs(range('a', 'z'));
->shouldIterateAs([
'a' => ['A'],
'b' => ['B'],
'c' => ['C'],
]);

$this::fromIterable(range('a', 'z'))
$this::fromIterable(range('a', 'e'))
->window(2)
->shouldIterateAs([
0 => [
Expand All @@ -4041,111 +4045,13 @@ public function it_can_window(): void
1 => 'd',
2 => 'e',
],
5 => [
0 => 'd',
1 => 'e',
2 => 'f',
],
6 => [
0 => 'e',
1 => 'f',
2 => 'g',
],
7 => [
0 => 'f',
1 => 'g',
2 => 'h',
],
8 => [
0 => 'g',
1 => 'h',
2 => 'i',
],
9 => [
0 => 'h',
1 => 'i',
2 => 'j',
],
10 => [
0 => 'i',
1 => 'j',
2 => 'k',
],
11 => [
0 => 'j',
1 => 'k',
2 => 'l',
],
12 => [
0 => 'k',
1 => 'l',
2 => 'm',
],
13 => [
0 => 'l',
1 => 'm',
2 => 'n',
],
14 => [
0 => 'm',
1 => 'n',
2 => 'o',
],
15 => [
0 => 'n',
1 => 'o',
2 => 'p',
],
16 => [
0 => 'o',
1 => 'p',
2 => 'q',
],
17 => [
0 => 'p',
1 => 'q',
2 => 'r',
],
18 => [
0 => 'q',
1 => 'r',
2 => 's',
],
19 => [
0 => 'r',
1 => 's',
2 => 't',
],
20 => [
0 => 's',
1 => 't',
2 => 'u',
],
21 => [
0 => 't',
1 => 'u',
2 => 'v',
],
22 => [
0 => 'u',
1 => 'v',
2 => 'w',
],
23 => [
0 => 'v',
1 => 'w',
2 => 'x',
],
24 => [
0 => 'w',
1 => 'x',
2 => 'y',
],
25 => [
0 => 'x',
1 => 'y',
2 => 'z',
],
]);

// Unsupported - but tested.
$this::fromIterable(range('a', 'e'))
->window(-2)
->shouldIterateAs([
[], [], [], [], [],
]);
}

Expand Down
2 changes: 1 addition & 1 deletion src/Contract/Operation/Windowable.php
Expand Up @@ -19,7 +19,7 @@ interface Windowable
{
/**
* Loop the collection yielding windows of data by adding a given number of items to the current item.
* Initially the windows yielded will be smaller, until size` 1 + $size` is reached.
* Initially the windows yielded will be smaller, until size `1 + $size` is reached.
*
* @see https://loophp-collection.readthedocs.io/en/stable/pages/api.html#window
*
Expand Down
39 changes: 17 additions & 22 deletions src/Operation/Window.php
Expand Up @@ -26,33 +26,28 @@ final class Window extends AbstractOperation
/**
* @pure
*
* @return Closure(int): Closure(Iterator<TKey, T>): Generator<TKey, T|list<T>>
* @return Closure(int): Closure(Iterator<TKey, T>): Generator<TKey, list<T>>
*/
public function __invoke(): Closure
{
return
/**
* @return Closure(Iterator<TKey, T>): Generator<TKey, T|list<T>>
* @return Closure(Iterator<TKey, T>): Generator<TKey, list<T>>
*/
static fn (int $size): Closure =>
/**
* @param Iterator<TKey, T> $iterator
*
* @return Generator<TKey, list<T>|T>
*/
static function (Iterator $iterator) use ($size): Generator {
if (0 === $size) {
return yield from $iterator;
}

++$size;
$size *= -1;

$stack = [];

foreach ($iterator as $key => $current) {
yield $key => $stack = array_slice([...$stack, $current], $size);
}
};
static function (int $size): Closure {
/** @var Closure(Iterator<TKey, T>): Generator<TKey, list<T>> $reduction */
$reduction = Reduction::of()(
/**
* @param list<T> $stack
* @param T $current
*
* @return list<T>
*/
static fn (array $stack, $current): array => array_slice([...$stack, $current], ++$size * -1)
)([]);

// Point free style.
return $reduction;
};
}
}

0 comments on commit e59b29b

Please sign in to comment.