Skip to content

Commit 0207ac4

Browse files
author
Jarek Jakubowski
committed
Fix constructing from an associative array; add slice and flatten methods
1 parent f1465ae commit 0207ac4

4 files changed

Lines changed: 114 additions & 26 deletions

File tree

composer.json

Lines changed: 16 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,22 @@
1212
}
1313
],
1414
"require": {
15-
"php": ">=7.1"
15+
"php": ">=7.1",
16+
"ext-json": "*"
17+
},
18+
"require-dev": {
19+
"phpunit/phpunit": "^9.4",
20+
"symplify/easy-coding-standard": "^8.3"
21+
},
22+
"autoload": {
23+
"psr-4": {
24+
"JarJak\\Collection\\": "src/JarJak/Collection"
25+
}
26+
},
27+
"autoload-dev": {
28+
"psr-4": {
29+
"Tests\\": "tests/"
30+
}
1631
},
1732
"scripts": {
1833
"post-update-cmd": "cp -n phpunit.xml.dist phpunit.xml",
@@ -26,19 +41,5 @@
2641
"csfix": [
2742
"php -d memory_limit=1024M vendor/bin/ecs check --fix"
2843
]
29-
},
30-
"autoload": {
31-
"psr-4": {
32-
"JarJak\\Collection\\": "src/JarJak/Collection"
33-
}
34-
},
35-
"autoload-dev": {
36-
"psr-4": {
37-
"Tests\\": "tests/"
38-
}
39-
},
40-
"require-dev": {
41-
"phpunit/phpunit": "^9.4",
42-
"symplify/easy-coding-standard": "^8.3"
4344
}
4445
}

ecs.php

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44

55
use PhpCsFixer\Fixer\ClassNotation\ClassDefinitionFixer;
66
use PhpCsFixer\Fixer\ControlStructure\YodaStyleFixer;
7+
use PhpCsFixer\Fixer\FunctionNotation\VoidReturnFixer;
78
use PhpCsFixer\Fixer\PhpTag\BlankLineAfterOpeningTagFixer;
89
use PhpCsFixer\Fixer\Whitespace\ArrayIndentationFixer;
910
use Symfony\Component\DependencyInjection\Loader\Configurator\ContainerConfigurator;
@@ -57,5 +58,8 @@
5758
ClassDefinitionFixer::class => [
5859
'*Test.php',
5960
],
61+
VoidReturnFixer::class => [
62+
'*Test.php',
63+
],
6064
]);
6165
};

src/JarJak/Collection/Collection.php

Lines changed: 24 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -10,15 +10,15 @@ public function __construct(...$items)
1010
{
1111
parent::__construct(\count($items));
1212

13-
foreach ($items as $i => $item) {
13+
foreach (array_values($items) as $i => $item) {
1414
$this[$i] = $item;
1515
}
1616
}
1717

1818
public static function from(iterable $array)
1919
{
20-
if (\is_array($array)) {
21-
return new static(...array_values($array));
20+
if (\is_array($array) || $array instanceof \ArrayAccess) {
21+
return new static(...(array) $array);
2222
}
2323

2424
return new static(...$array);
@@ -53,7 +53,22 @@ public function flatMap(\Closure $callback)
5353
return static::from(
5454
array_merge(
5555
...array_map(
56-
$callback,
56+
'array_values',
57+
array_map(
58+
$callback,
59+
$this->toArray()
60+
)
61+
)
62+
)
63+
);
64+
}
65+
66+
public function flatten()
67+
{
68+
return static::from(
69+
array_merge(
70+
...array_map(
71+
'array_values',
5772
$this->toArray()
5873
)
5974
)
@@ -151,6 +166,11 @@ public function first()
151166
return $iterator->current();
152167
}
153168

169+
public function slice(?int $maxItems, int $itemsToSkipFromBeginning = 0): self
170+
{
171+
return static::from(array_slice($this->toArray(), $itemsToSkipFromBeginning, $maxItems));
172+
}
173+
154174
public function jsonSerialize(): array
155175
{
156176
return $this->toArray();

tests/CollectionTest.php

Lines changed: 70 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ class CollectionTest extends TestCase
1212
/**
1313
* @dataProvider uniqueDataProvider
1414
*/
15-
public function testUnique($input, $expected): void
15+
public function testUnique($input, $expected)
1616
{
1717
$service = new Collection(...$input);
1818
$this->assertSame($expected, $service->unique()->toArray());
@@ -51,7 +51,7 @@ public function uniqueDataProvider(): iterable
5151
];
5252
}
5353

54-
public function testSortFlatMap(): void
54+
public function testSortFlatMap()
5555
{
5656
$dateCollection = new class(
5757
new \DateTimeImmutable('now'),
@@ -94,7 +94,37 @@ public function __construct(\DateTimeInterface ...$items)
9494
$this->assertSame($expected, $result->toArray());
9595
}
9696

97-
public function testFirst(): void
97+
public function testFlatMapOnDeepAssociative()
98+
{
99+
$input = [
100+
['foo' => 'bar'],
101+
['foo' => 'baz'],
102+
];
103+
$expected = ['BAR', 'BAZ'];
104+
105+
$result = Collection::from($input)
106+
->flatMap(function (array $values): array {
107+
return array_map('strtoupper', $values);
108+
});
109+
110+
$this->assertSame($expected, $result->toArray());
111+
}
112+
113+
public function testFlatten()
114+
{
115+
$input = [
116+
['foo' => 'bar'],
117+
['foo' => 'baz'],
118+
];
119+
$expected = ['bar', 'baz'];
120+
121+
$collection = Collection::from($input);
122+
$result = $collection->flatten();
123+
124+
$this->assertSame($expected, $result->toArray());
125+
}
126+
127+
public function testFirst()
98128
{
99129
$collection = Collection::from(range(1, 10));
100130
$sum = 0;
@@ -110,7 +140,7 @@ public function testFirst(): void
110140
$this->assertSame($emptyCollection->first(), null);
111141
}
112142

113-
public function testAdd(): void
143+
public function testAdd()
114144
{
115145
$collection = Collection::from(range(1, 3));
116146
$collection = $collection->add(5);
@@ -121,11 +151,44 @@ public function testAdd(): void
121151
$this->assertSame($collection->toArray(), [1, 2, 3, 5, 5, 3]);
122152
}
123153

124-
public function testFromAssociativeArray(): void
154+
public function testSlice()
155+
{
156+
$emptyCollection = new Collection();
157+
$collection = new Collection(...['a', 'b', 'c', 'd', 'e']);
158+
159+
$this->assertSame([], $emptyCollection->slice(null)->toArray());
160+
$this->assertSame(['a', 'b', 'c', 'd', 'e'], $collection->slice(null)->toArray());
161+
162+
$this->assertSame([], $emptyCollection->slice(3)->toArray());
163+
$this->assertSame(['a', 'b', 'c'], $collection->slice(3)->toArray());
164+
165+
$this->assertSame([], $emptyCollection->slice(null)->toArray());
166+
$this->assertSame(['c', 'd', 'e'], $collection->slice(null, 2)->toArray());
167+
168+
$this->assertSame([], $emptyCollection->slice(2, 1)->toArray());
169+
$this->assertSame(['b', 'c'], $collection->slice(2, 1)->toArray());
170+
}
171+
172+
public function testFromAssociativeArray()
125173
{
126174
$input = ['foo' => 'bar', 'bar' => 'baz'];
127175

128-
$service2 = Collection::from($input);
129-
$this->assertSame(array_values($input), $service2->toArray());
176+
$collection1 = Collection::from($input);
177+
$this->assertSame(array_values($input), $collection1->toArray());
178+
$collection2 = new Collection(...$input);
179+
$this->assertSame(array_values($input), $collection2->toArray());
180+
}
181+
182+
public function testFromAssociativeIterable()
183+
{
184+
$inputIterable = function (): iterable {
185+
yield 'foo' => 'bar';
186+
yield 'bar' => 'baz';
187+
};
188+
189+
$collection1 = Collection::from($inputIterable());
190+
$this->assertSame(array_values(iterator_to_array($inputIterable())), $collection1->toArray());
191+
$collection2 = new Collection(...$inputIterable());
192+
$this->assertSame(array_values(iterator_to_array($inputIterable())), $collection2->toArray());
130193
}
131194
}

0 commit comments

Comments
 (0)