Skip to content

Commit d3c90d4

Browse files
authored
Merge pull request #24 from samsonasik/add-collector-class
Add Collector class
2 parents d71ac82 + 7eab4e4 commit d3c90d4

File tree

3 files changed

+176
-0
lines changed

3 files changed

+176
-0
lines changed

README.md

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ Features
1818
- [x] Verify at least times: `once()`, `twice()`, `times()`
1919
- [x] Verify exact times: `once()`, `twice()`, `times()`
2020
- [x] Search data: `first()`, `last()`, `rows()`
21+
- [x] Collect data with filter and transform
2122

2223
Installation
2324
------------
@@ -366,4 +367,37 @@ $limit = 1;
366367
var_dump(
367368
Finder::rows($data, $filter, limit: $limit)
368369
); // [1]
370+
```
371+
372+
**4. Collector**
373+
---------------
374+
375+
It collect filtered data, with new transformed each data found:
376+
377+
**Before**
378+
379+
```php
380+
$newArray = [];
381+
382+
foreach ($data as $datum) {
383+
if (is_string($datum)) {
384+
$newArray[] = trim($datum);
385+
}
386+
}
387+
```
388+
389+
**After**
390+
391+
```php
392+
use ArrayLookup\Collector;
393+
394+
$when = fn ($datum): bool => is_string($datum);
395+
$limit = 2;
396+
$transform = fn ($datum): string => trim($datum);
397+
398+
$newArray = Collector::setUp($data)
399+
->when($when)
400+
->withLimit(2) // optional to only collect some data provided by limit config
401+
->withTransform($transform)
402+
->getResults();
369403
```

src/Collector.php

Lines changed: 92 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,92 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace ArrayLookup;
6+
7+
use Traversable;
8+
use Webmozart\Assert\Assert;
9+
10+
final class Collector
11+
{
12+
/** @var array<int|string, mixed>|Traversable<int|string, mixed> */
13+
private iterable $data = [];
14+
15+
/** @var callable(mixed $datum, int|string|null $key=): bool|null */
16+
private $when;
17+
18+
/** @var callable(mixed $datum, int|string|null $key=): mixed */
19+
private $transform;
20+
21+
private ?int $limit = null;
22+
23+
/**
24+
* @param array<int|string, mixed>|Traversable<int|string, mixed> $data
25+
*/
26+
public static function setUp(iterable $data): self
27+
{
28+
$self = new self();
29+
$self->data = $data;
30+
31+
return $self;
32+
}
33+
34+
/**
35+
* @param callable(mixed $datum, int|string|null $key=): bool $filter
36+
*/
37+
public function when(callable $filter): self
38+
{
39+
$this->when = $filter;
40+
return $this;
41+
}
42+
43+
public function withLimit(int $limit): self
44+
{
45+
Assert::positiveInteger($limit);
46+
$this->limit = $limit;
47+
48+
return $this;
49+
}
50+
51+
/**
52+
* @param callable(mixed $datum, int|string|null $key=): mixed $transform
53+
*/
54+
public function withTransform(callable $transform): self
55+
{
56+
$this->transform = $transform;
57+
return $this;
58+
}
59+
60+
/**
61+
* @return mixed[]
62+
*/
63+
public function getResults(): array
64+
{
65+
// ensure when property is set early via ->when() and ->withTransform() method
66+
Assert::isCallable($this->when);
67+
Assert::isCallable($this->transform);
68+
69+
$count = 0;
70+
$collectedData = [];
71+
72+
foreach ($this->data as $key => $datum) {
73+
$isFound = ($this->when)($datum, $key);
74+
75+
Assert::boolean($isFound);
76+
77+
if (! $isFound) {
78+
continue;
79+
}
80+
81+
$collectedData[] = ($this->transform)($datum, $key);
82+
83+
++$count;
84+
85+
if ($this->limit === $count) {
86+
break;
87+
}
88+
}
89+
90+
return $collectedData;
91+
}
92+
}

tests/CollectorTest.php

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace ArrayLookup\Tests;
6+
7+
use ArrayLookup\Collector;
8+
use PHPUnit\Framework\TestCase;
9+
use stdClass;
10+
11+
use function is_string;
12+
use function trim;
13+
14+
final class CollectorTest extends TestCase
15+
{
16+
public function testWithoutLimit(): void
17+
{
18+
$data = [
19+
' a ',
20+
' b ',
21+
' c ',
22+
new stdClass(),
23+
];
24+
25+
$results = Collector::setUp($data)
26+
->when(fn (mixed $datum): bool => is_string($datum))
27+
->withTransform(fn (string $datum): string => trim($datum))
28+
->getResults();
29+
30+
$this->assertSame(['a', 'b', 'c'], $results);
31+
}
32+
33+
public function testWithLimit(): void
34+
{
35+
$data = [
36+
' a ',
37+
' b ',
38+
' c ',
39+
new stdClass(),
40+
];
41+
42+
$results = Collector::setUp($data)
43+
->when(fn (mixed $datum): bool => is_string($datum))
44+
->withTransform(fn (string $datum): string => trim($datum))
45+
->withLimit(1)
46+
->getResults();
47+
48+
$this->assertSame(['a'], $results);
49+
}
50+
}

0 commit comments

Comments
 (0)