Skip to content

Commit

Permalink
1. Function map(): params order changed, mapping of multiple collec…
Browse files Browse the repository at this point in the history
…tions support added.

2. Tests updated for `map()`.
3. README updated.
  • Loading branch information
Smoren committed Jan 10, 2023
1 parent 87d6fbc commit 87d682a
Show file tree
Hide file tree
Showing 4 changed files with 196 additions and 38 deletions.
114 changes: 91 additions & 23 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,25 +6,47 @@
![Build and test](https://github.com/Smoren/sequence-php/actions/workflows/test_master.yml/badge.svg)
[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)

Python-like sequences with iterators for PHP
Python-like sequences with iterators for PHP.

### How to install to your project
## How to install to your project
```
composer require smoren/sequence
```

### Unit testing
```
composer install
composer test-init
composer test
```
## Quick Reference

### Loops
| Functionality | Description | Code Snippet |
|---------------------------------------|------------------------------|---------------------------------------------------|
| [`Range-based for`](#Range-based-for) | Python-like range-based loop | `foreach(xrange($start, $size, $step) as $value)` |

### Sequences
| Class | Description | Code Snippet |
|----------------------------------------|---------------------------------|-----------------------------------------------------------------------------|
| [`Range`](#Range) | Iterable arithmetic progression | `new Range($start, $size, $step)` |
| [`Exponential`](#Exponential) | Iterable geometric progression | `new Exponential($start, $size, $step)` |
| [`DynamicSequence`](#Dynamic-Sequence) | Callback-configurable sequence | `new DynamicSequence($start, $size, $nextValueGetter, $indexedValueGetter)` |

### Data containers
| Class | Description | Code Snippet |
|----------------------------------|--------------------------|----------------------------|
| [`IndexedArray`](#Indexed-Array) | Python-like indexed list | `new IndexedArray($array)` |

### Functions
| Function | Description | Code Snippet |
|---------------------|--------------------------------------------------------------------------|------------------------------------------------|
| [`xrange`](#xrange) | Creates iterable range | `xrange($start, $size, $step)` |
| [`map`](#map) | Maps iterable collections and returns IndexedArray of mapped values | `map($mapper, ...$collections)` |
| [`filter`](#filter) | Filters iterable collection and returning IndexedArray of filtered items | `filter($collection, $filter)` |
| [`reduce`](#reduce) | Reduces an iterable collection | `reduce($collection, $reducer, $initialValue)` |

## Usage

### Usage
### Loops

#### Range-based for (python-like)
#### Range-based for

Unlike the built-in function `range()`, `xrange()` does not create an array, but a `Traversable` object
Unlike the PHP built-in function `range()`, `xrange()` does not create an array, but a `Traversable` object
that takes up a small amount of memory, regardless of the number of elements in the sequence.

```php
Expand All @@ -46,8 +68,16 @@ foreach(xrange(1, 5, 2) as $i) { // start: 1; count: 5; step: 2
// 1 3 5 7 9
```

### Sequences

#### Range

Iterable arithmetic progression.

```new Range(int|float $start, ?int $size, int|float $step)```

For infinite sequence use `$size = null`.

```php
use Smoren\Sequence\Structs\Range;
use Smoren\Sequence\Exceptions\OutOfRangeException;
Expand Down Expand Up @@ -103,6 +133,12 @@ foreach($range as $value) {

#### Exponential

Iterable geometric progression.

```new Exponential(int|float $start, ?int $size, int|float $step)```

For infinite sequence use `$size = null`.

```php
use Smoren\Sequence\Structs\Exponential;
use Smoren\Sequence\Exceptions\OutOfRangeException;
Expand Down Expand Up @@ -158,7 +194,13 @@ foreach($sequence as $value) {
// 0.5 0.25 0.125...
```

#### DynamicSequence
#### Dynamic Sequence

Implementation of sequence configured with callables.

```new DynamicSequence(mixed $start, ?int $size, callable $nextValueGetter, ?callable $indexedValueGetter = null)```

For infinite sequence use `$size = null`.

```php
use Smoren\Sequence\Structs\DynamicSequence;
Expand All @@ -174,7 +216,17 @@ var_dump(iterator_to_array($sequence));
// [1, 2, 3, 4, 5]
```

#### IndexedArray
### Data containers

#### Indexed Array

Python-like indexed list.

Its keys are always an unbroken sequence of natural numbers starting from zero.

It is also allowed to access array elements from the end with negative indices.

OutOfRangeException will be thrown when trying to access a non-existent index.

```php
use Smoren\Sequence\Structs\IndexedArray;
Expand Down Expand Up @@ -213,9 +265,13 @@ try {
}
```

### Functions

#### xrange

Function for creating iterable range.
Creates iterable range.

Works like `xrange()` function in python2 or `range()` function in python3.

```xrange(int $start, ?int $size = null, int $step = 1): Range```

Expand All @@ -237,24 +293,25 @@ print_r(iterator_to_array($range));

#### map

Function for mapping iterable collection and creating IndexedArray of mapped values as a result.
Maps iterable collection and creating IndexedArray of mapped values as a result.

```map(iterable $collection, callable $mapper): IndexedArray```

```php
use function Smoren\Sequence\Functions\map;

$input = [1, 2, 3, 4, 5];
$result = map($input, static function($item) {
return $item + 2;
});
$ids = [1, 2, 3];
$names = ['Mary', 'Jane', 'Alice'];
$result = map(static function(int $id, string $name) {
return "{$id}. {$name}";
}, $ids, $names);
print_r($result->toArray());
// [3, 4, 5, 6, 7]
// ['1. Mary', '2. Jane', '3. Alice']
```

#### filter

Function for filtering iterable collection and returning IndexedArray of filtered items.
Filters iterable collection and returning IndexedArray of filtered items.

```filter(iterable $collection, callable $filter): IndexedArray```

Expand All @@ -271,9 +328,9 @@ print_r($result->toArray());

#### reduce

Function for reduction of iterable collection.
Reduces an iterable collection.

```reduce(iterable $collection, callable $reducer, mixed $initialValue = null): IndexedArray```
```reduce(iterable $collection, callable $reducer, mixed $initialValue = null): mixed```

```php
use function Smoren\Sequence\Functions\reduce;
Expand All @@ -285,3 +342,14 @@ $result = reduce($input, static function($carry, $item) {
var_dump($result);
// 15
```

## Unit testing
```
composer install
composer test-init
composer test
```

## License

PHP Sequence is licensed under the MIT License.
6 changes: 3 additions & 3 deletions src/Structs/DynamicSequence.php
Original file line number Diff line number Diff line change
Expand Up @@ -28,17 +28,17 @@ class DynamicSequence extends Sequence
* @param T $start start of the sequence
* @param int<0, max>|null $size size of the sequence (infinite if null)
* @param callable(T $previousValue): T $nextValueGetter getter for the next value
* @param (callable(int $index, T $start): T)|null $indexValueGetter getter for the i-th value
* @param (callable(int $index, T $start): T)|null $indexedValueGetter getter for the i-th value
*/
public function __construct(
$start,
?int $size,
callable $nextValueGetter,
?callable $indexValueGetter = null
?callable $indexedValueGetter = null
) {
parent::__construct($start, $size);
$this->nextValueGetter = $nextValueGetter;
$this->indexValueGetter = $indexValueGetter;
$this->indexValueGetter = $indexedValueGetter;
}

/**
Expand Down
27 changes: 22 additions & 5 deletions src/functions.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,9 @@

namespace Smoren\Sequence\Functions;

use ArrayIterator;
use IteratorIterator;
use MultipleIterator;
use Smoren\Sequence\Structs\IndexedArray;
use Smoren\Sequence\Structs\Range;

Expand All @@ -24,22 +27,36 @@ function xrange(int $start, ?int $size = null, int $step = 1): Range
}

/**
* Maps iterable collection and returns IndexedArray of mapped values.
* Maps iterable collections and returns IndexedArray of mapped values.
*
* @template TInput
* @template TOutput
*
* @param iterable<TInput> $collection
* @param callable(TInput $item): TOutput $mapper
* @param iterable<TInput> $collections
*
* @return IndexedArray<TOutput>
*/
function map(iterable $collection, callable $mapper): IndexedArray
function map(callable $mapper, iterable ...$collections): IndexedArray
{
$result = new IndexedArray();

foreach($collection as $item) {
$result[] = $mapper($item);
if(count($collections) === 0) {
return $result;
}

$it = new MultipleIterator(MultipleIterator::MIT_NEED_ALL|MultipleIterator::MIT_KEYS_NUMERIC);

foreach($collections as $collection) {
if(is_array($collection)) {
$collection = new ArrayIterator($collection);
}

$it->attachIterator(new IteratorIterator($collection));
}

foreach($it as $values) {
$result[] = $mapper(...$values);
}

return $result;
Expand Down
87 changes: 80 additions & 7 deletions tests/unit/FunctionsTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,7 @@ public function testMap(iterable $data, callable $mapper, array $expected): void
{
// Given
// When
$mapped = map($data, $mapper);
$mapped = map($mapper, ...$data);

// Then
$this->assertEquals($expected, $mapped->toArray());
Expand All @@ -108,36 +108,109 @@ static function(array $item) {
],
[
[
['name' => 'John'],
['name' => 'Jane'],
['name' => 'Jim'],
[],
],
static function(array $item) {
return $item['name'];
},
[],
],
[
[
[
['name' => 'John'],
['name' => 'Jane'],
['name' => 'Jim'],
],
],
static function(array $item) {
return $item['name'];
},
['John', 'Jane', 'Jim'],
],
[
[1, 2, 3],
[
[1, 2, 3],
],
static function($item) {
return $item + 1;
},
[2, 3, 4],
],
[
[1, 2, 3],
[
[1, 2, 3],
],
static function($item) {
return $item;
},
[1, 2, 3],
],
[
[1, 2, 3],
[
[1, 2, 3],
],
static function() {
return null;
},
[null, null, null],
],
[
[
[
11,
22,
33,
],
[
['name' => 'John'],
['name' => 'Jane'],
['name' => 'Jim'],
],
],
static function(int $id, array $data) {
return [$id => $data['name']];
},
[[11 => 'John'], [22 => 'Jane'], [33 => 'Jim']],
],
[
[
[
11,
22,
33,
44,
],
[
['name' => 'John'],
['name' => 'Jane'],
['name' => 'Jim'],
],
],
static function(int $id, array $data) {
return [$id => $data['name']];
},
[[11 => 'John'], [22 => 'Jane'], [33 => 'Jim']],
],
[
[
[
11,
22,
33,
],
[
['name' => 'John'],
['name' => 'Jane'],
['name' => 'Jim'],
['name' => 'Mary'],
],
],
static function(int $id, array $data) {
return [$id => $data['name']];
},
[[11 => 'John'], [22 => 'Jane'], [33 => 'Jim']],
],
];
}

Expand Down

0 comments on commit 87d682a

Please sign in to comment.