Skip to content

Commit 87d682a

Browse files
committed
1. Function map(): params order changed, mapping of multiple collections support added.
2. Tests updated for `map()`. 3. README updated.
1 parent 87d6fbc commit 87d682a

File tree

4 files changed

+196
-38
lines changed

4 files changed

+196
-38
lines changed

README.md

Lines changed: 91 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -6,25 +6,47 @@
66
![Build and test](https://github.com/Smoren/sequence-php/actions/workflows/test_master.yml/badge.svg)
77
[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
88

9-
Python-like sequences with iterators for PHP
9+
Python-like sequences with iterators for PHP.
1010

11-
### How to install to your project
11+
## How to install to your project
1212
```
1313
composer require smoren/sequence
1414
```
1515

16-
### Unit testing
17-
```
18-
composer install
19-
composer test-init
20-
composer test
21-
```
16+
## Quick Reference
17+
18+
### Loops
19+
| Functionality | Description | Code Snippet |
20+
|---------------------------------------|------------------------------|---------------------------------------------------|
21+
| [`Range-based for`](#Range-based-for) | Python-like range-based loop | `foreach(xrange($start, $size, $step) as $value)` |
22+
23+
### Sequences
24+
| Class | Description | Code Snippet |
25+
|----------------------------------------|---------------------------------|-----------------------------------------------------------------------------|
26+
| [`Range`](#Range) | Iterable arithmetic progression | `new Range($start, $size, $step)` |
27+
| [`Exponential`](#Exponential) | Iterable geometric progression | `new Exponential($start, $size, $step)` |
28+
| [`DynamicSequence`](#Dynamic-Sequence) | Callback-configurable sequence | `new DynamicSequence($start, $size, $nextValueGetter, $indexedValueGetter)` |
29+
30+
### Data containers
31+
| Class | Description | Code Snippet |
32+
|----------------------------------|--------------------------|----------------------------|
33+
| [`IndexedArray`](#Indexed-Array) | Python-like indexed list | `new IndexedArray($array)` |
34+
35+
### Functions
36+
| Function | Description | Code Snippet |
37+
|---------------------|--------------------------------------------------------------------------|------------------------------------------------|
38+
| [`xrange`](#xrange) | Creates iterable range | `xrange($start, $size, $step)` |
39+
| [`map`](#map) | Maps iterable collections and returns IndexedArray of mapped values | `map($mapper, ...$collections)` |
40+
| [`filter`](#filter) | Filters iterable collection and returning IndexedArray of filtered items | `filter($collection, $filter)` |
41+
| [`reduce`](#reduce) | Reduces an iterable collection | `reduce($collection, $reducer, $initialValue)` |
42+
43+
## Usage
2244

23-
### Usage
45+
### Loops
2446

25-
#### Range-based for (python-like)
47+
#### Range-based for
2648

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

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

71+
### Sequences
72+
4973
#### Range
5074

75+
Iterable arithmetic progression.
76+
77+
```new Range(int|float $start, ?int $size, int|float $step)```
78+
79+
For infinite sequence use `$size = null`.
80+
5181
```php
5282
use Smoren\Sequence\Structs\Range;
5383
use Smoren\Sequence\Exceptions\OutOfRangeException;
@@ -103,6 +133,12 @@ foreach($range as $value) {
103133

104134
#### Exponential
105135

136+
Iterable geometric progression.
137+
138+
```new Exponential(int|float $start, ?int $size, int|float $step)```
139+
140+
For infinite sequence use `$size = null`.
141+
106142
```php
107143
use Smoren\Sequence\Structs\Exponential;
108144
use Smoren\Sequence\Exceptions\OutOfRangeException;
@@ -158,7 +194,13 @@ foreach($sequence as $value) {
158194
// 0.5 0.25 0.125...
159195
```
160196

161-
#### DynamicSequence
197+
#### Dynamic Sequence
198+
199+
Implementation of sequence configured with callables.
200+
201+
```new DynamicSequence(mixed $start, ?int $size, callable $nextValueGetter, ?callable $indexedValueGetter = null)```
202+
203+
For infinite sequence use `$size = null`.
162204

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

177-
#### IndexedArray
219+
### Data containers
220+
221+
#### Indexed Array
222+
223+
Python-like indexed list.
224+
225+
Its keys are always an unbroken sequence of natural numbers starting from zero.
226+
227+
It is also allowed to access array elements from the end with negative indices.
228+
229+
OutOfRangeException will be thrown when trying to access a non-existent index.
178230

179231
```php
180232
use Smoren\Sequence\Structs\IndexedArray;
@@ -213,9 +265,13 @@ try {
213265
}
214266
```
215267

268+
### Functions
269+
216270
#### xrange
217271

218-
Function for creating iterable range.
272+
Creates iterable range.
273+
274+
Works like `xrange()` function in python2 or `range()` function in python3.
219275

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

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

238294
#### map
239295

240-
Function for mapping iterable collection and creating IndexedArray of mapped values as a result.
296+
Maps iterable collection and creating IndexedArray of mapped values as a result.
241297

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

244300
```php
245301
use function Smoren\Sequence\Functions\map;
246302

247-
$input = [1, 2, 3, 4, 5];
248-
$result = map($input, static function($item) {
249-
return $item + 2;
250-
});
303+
$ids = [1, 2, 3];
304+
$names = ['Mary', 'Jane', 'Alice'];
305+
$result = map(static function(int $id, string $name) {
306+
return "{$id}. {$name}";
307+
}, $ids, $names);
251308
print_r($result->toArray());
252-
// [3, 4, 5, 6, 7]
309+
// ['1. Mary', '2. Jane', '3. Alice']
253310
```
254311

255312
#### filter
256313

257-
Function for filtering iterable collection and returning IndexedArray of filtered items.
314+
Filters iterable collection and returning IndexedArray of filtered items.
258315

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

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

272329
#### reduce
273330

274-
Function for reduction of iterable collection.
331+
Reduces an iterable collection.
275332

276-
```reduce(iterable $collection, callable $reducer, mixed $initialValue = null): IndexedArray```
333+
```reduce(iterable $collection, callable $reducer, mixed $initialValue = null): mixed```
277334

278335
```php
279336
use function Smoren\Sequence\Functions\reduce;
@@ -285,3 +342,14 @@ $result = reduce($input, static function($carry, $item) {
285342
var_dump($result);
286343
// 15
287344
```
345+
346+
## Unit testing
347+
```
348+
composer install
349+
composer test-init
350+
composer test
351+
```
352+
353+
## License
354+
355+
PHP Sequence is licensed under the MIT License.

src/Structs/DynamicSequence.php

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -28,17 +28,17 @@ class DynamicSequence extends Sequence
2828
* @param T $start start of the sequence
2929
* @param int<0, max>|null $size size of the sequence (infinite if null)
3030
* @param callable(T $previousValue): T $nextValueGetter getter for the next value
31-
* @param (callable(int $index, T $start): T)|null $indexValueGetter getter for the i-th value
31+
* @param (callable(int $index, T $start): T)|null $indexedValueGetter getter for the i-th value
3232
*/
3333
public function __construct(
3434
$start,
3535
?int $size,
3636
callable $nextValueGetter,
37-
?callable $indexValueGetter = null
37+
?callable $indexedValueGetter = null
3838
) {
3939
parent::__construct($start, $size);
4040
$this->nextValueGetter = $nextValueGetter;
41-
$this->indexValueGetter = $indexValueGetter;
41+
$this->indexValueGetter = $indexedValueGetter;
4242
}
4343

4444
/**

src/functions.php

Lines changed: 22 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,9 @@
22

33
namespace Smoren\Sequence\Functions;
44

5+
use ArrayIterator;
6+
use IteratorIterator;
7+
use MultipleIterator;
58
use Smoren\Sequence\Structs\IndexedArray;
69
use Smoren\Sequence\Structs\Range;
710

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

2629
/**
27-
* Maps iterable collection and returns IndexedArray of mapped values.
30+
* Maps iterable collections and returns IndexedArray of mapped values.
2831
*
2932
* @template TInput
3033
* @template TOutput
3134
*
32-
* @param iterable<TInput> $collection
3335
* @param callable(TInput $item): TOutput $mapper
36+
* @param iterable<TInput> $collections
3437
*
3538
* @return IndexedArray<TOutput>
3639
*/
37-
function map(iterable $collection, callable $mapper): IndexedArray
40+
function map(callable $mapper, iterable ...$collections): IndexedArray
3841
{
3942
$result = new IndexedArray();
4043

41-
foreach($collection as $item) {
42-
$result[] = $mapper($item);
44+
if(count($collections) === 0) {
45+
return $result;
46+
}
47+
48+
$it = new MultipleIterator(MultipleIterator::MIT_NEED_ALL|MultipleIterator::MIT_KEYS_NUMERIC);
49+
50+
foreach($collections as $collection) {
51+
if(is_array($collection)) {
52+
$collection = new ArrayIterator($collection);
53+
}
54+
55+
$it->attachIterator(new IteratorIterator($collection));
56+
}
57+
58+
foreach($it as $values) {
59+
$result[] = $mapper(...$values);
4360
}
4461

4562
return $result;

tests/unit/FunctionsTest.php

Lines changed: 80 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -87,7 +87,7 @@ public function testMap(iterable $data, callable $mapper, array $expected): void
8787
{
8888
// Given
8989
// When
90-
$mapped = map($data, $mapper);
90+
$mapped = map($mapper, ...$data);
9191

9292
// Then
9393
$this->assertEquals($expected, $mapped->toArray());
@@ -108,36 +108,109 @@ static function(array $item) {
108108
],
109109
[
110110
[
111-
['name' => 'John'],
112-
['name' => 'Jane'],
113-
['name' => 'Jim'],
111+
[],
112+
],
113+
static function(array $item) {
114+
return $item['name'];
115+
},
116+
[],
117+
],
118+
[
119+
[
120+
[
121+
['name' => 'John'],
122+
['name' => 'Jane'],
123+
['name' => 'Jim'],
124+
],
114125
],
115126
static function(array $item) {
116127
return $item['name'];
117128
},
118129
['John', 'Jane', 'Jim'],
119130
],
120131
[
121-
[1, 2, 3],
132+
[
133+
[1, 2, 3],
134+
],
122135
static function($item) {
123136
return $item + 1;
124137
},
125138
[2, 3, 4],
126139
],
127140
[
128-
[1, 2, 3],
141+
[
142+
[1, 2, 3],
143+
],
129144
static function($item) {
130145
return $item;
131146
},
132147
[1, 2, 3],
133148
],
134149
[
135-
[1, 2, 3],
150+
[
151+
[1, 2, 3],
152+
],
136153
static function() {
137154
return null;
138155
},
139156
[null, null, null],
140157
],
158+
[
159+
[
160+
[
161+
11,
162+
22,
163+
33,
164+
],
165+
[
166+
['name' => 'John'],
167+
['name' => 'Jane'],
168+
['name' => 'Jim'],
169+
],
170+
],
171+
static function(int $id, array $data) {
172+
return [$id => $data['name']];
173+
},
174+
[[11 => 'John'], [22 => 'Jane'], [33 => 'Jim']],
175+
],
176+
[
177+
[
178+
[
179+
11,
180+
22,
181+
33,
182+
44,
183+
],
184+
[
185+
['name' => 'John'],
186+
['name' => 'Jane'],
187+
['name' => 'Jim'],
188+
],
189+
],
190+
static function(int $id, array $data) {
191+
return [$id => $data['name']];
192+
},
193+
[[11 => 'John'], [22 => 'Jane'], [33 => 'Jim']],
194+
],
195+
[
196+
[
197+
[
198+
11,
199+
22,
200+
33,
201+
],
202+
[
203+
['name' => 'John'],
204+
['name' => 'Jane'],
205+
['name' => 'Jim'],
206+
['name' => 'Mary'],
207+
],
208+
],
209+
static function(int $id, array $data) {
210+
return [$id => $data['name']];
211+
},
212+
[[11 => 'John'], [22 => 'Jane'], [33 => 'Jim']],
213+
],
141214
];
142215
}
143216

0 commit comments

Comments
 (0)