Skip to content

Commit a0ac9b2

Browse files
committed
introduce sliding and grouped methods to Set
1 parent 3191002 commit a0ac9b2

File tree

2 files changed

+177
-0
lines changed

2 files changed

+177
-0
lines changed

src/Collection/Set.php

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -356,4 +356,38 @@ public function drop(int $n): self
356356

357357
return self::fromPointer($sliced);
358358
}
359+
360+
/**
361+
* @return self<self<T>>|self<T>
362+
*/
363+
public function sliding(int $size, int $step): self
364+
{
365+
if ($size <= 0 || $step <= 0) {
366+
throw new \InvalidArgumentException("size ($size) and step ($step) must both be positive");
367+
}
368+
369+
if ($this->isEmpty()) {
370+
return self::empty();
371+
}
372+
373+
$result = [];
374+
$array = &$this->elements;
375+
$length = count($array);
376+
377+
for ($i = 0; $i < $length; $i += $step) {
378+
$chunkSize = min($size, $length - $i);
379+
$chunk = array_slice($array, $i, $chunkSize);
380+
$result[] = self::fromPointer($chunk);
381+
}
382+
383+
return self::fromPointer($result);
384+
}
385+
386+
/**
387+
* @return self<self<T>>
388+
*/
389+
public function grouped(int $size): self
390+
{
391+
return $this->sliding($size, $size);
392+
}
359393
}

tests/Collection/SetTest.php

Lines changed: 143 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -284,4 +284,147 @@ public function testSetAddAll(): void
284284
self::assertTrue(Set::empty()->equals(Set::empty()->addAll(Set::empty())));
285285
self::assertTrue(Set::of('a', 'b', 'c')->equals(Set::of('a')->addAll(Set::of('a', 'b', 'c'))));
286286
}
287+
288+
public function testSlidingOnEmpty(): void
289+
{
290+
$set = Set::empty();
291+
$result = $set->sliding(1, 1);
292+
293+
self::assertEquals(0, $result->length());
294+
}
295+
296+
public function testSlidingBigWindow(): void
297+
{
298+
$set = Set::ofAll([1, 2, 3, 4, 5]);
299+
$result = $set->sliding(2, 4);
300+
301+
self::assertEquals(2, $result->length());
302+
self::assertTrue(Set::of(1, 2)->equals($result->toArray()[0]));
303+
self::assertTrue(Set::of(5)->equals($result->toArray()[1]));
304+
}
305+
306+
public function testSetSlidingWithSameStepAndSize(): void
307+
{
308+
$set = Set::of(1, 2, 3, 4, 5, 6);
309+
$result = $set->sliding(2, 2);
310+
311+
self::assertEquals(3, $result->length());
312+
self::assertTrue(Set::of(1, 2)->equals($result->toArray()[0]));
313+
self::assertTrue(Set::of(3, 4)->equals($result->toArray()[1]));
314+
self::assertTrue(Set::of(5, 6)->equals($result->toArray()[2]));
315+
}
316+
317+
public function testSetSlidingWithSameStepAndSizeLastRangeDifferent(): void
318+
{
319+
$set = Set::of(1, 2, 3, 4, 5, 6, 7, 8);
320+
$result = $set->sliding(3, 3);
321+
322+
self::assertEquals(3, $result->length());
323+
self::assertTrue(Set::of(1, 2, 3)->equals($result->toArray()[0]));
324+
self::assertTrue(Set::of(4, 5, 6)->equals($result->toArray()[1]));
325+
self::assertTrue(Set::of(7, 8)->equals($result->toArray()[2]));
326+
}
327+
328+
public function testSetSlidingWithSameStepAndSizeLastRangeDifferent100(): void
329+
{
330+
$set = Set::ofAll(range(1, 100));
331+
$result = $set->sliding(10, 5);
332+
333+
self::assertEquals(20, $result->length());
334+
self::assertTrue(Set::of(1, 2, 3, 4, 5, 6, 7, 8, 9, 10)->equals($result->toArray()[0]));
335+
self::assertTrue(Set::of(6, 7, 8, 9, 10, 11, 12, 13, 14, 15)->equals($result->toArray()[1]));
336+
self::assertTrue(Set::of(96, 97, 98, 99, 100)->equals($result->toArray()[19]));
337+
}
338+
339+
public function testSetSlidingWithLargerSize(): void
340+
{
341+
$set = Set::of(1, 2, 3, 4, 5);
342+
$result = $set->sliding(3, 1);
343+
344+
self::assertEquals(5, $result->length());
345+
self::assertTrue(Set::of(1, 2, 3)->equals($result->toArray()[0]));
346+
self::assertTrue(Set::of(2, 3, 4)->equals($result->toArray()[1]));
347+
self::assertTrue(Set::of(3, 4, 5)->equals($result->toArray()[2]));
348+
self::assertTrue(Set::of(4, 5)->equals($result->toArray()[3]));
349+
self::assertTrue(Set::of(5)->equals($result->toArray()[4]));
350+
}
351+
352+
public function testSetGroupedOnEmpty(): void
353+
{
354+
$set = Set::empty();
355+
$result = $set->grouped(2);
356+
357+
self::assertEquals(0, $result->length());
358+
}
359+
360+
public function testSetGroupedWithAllWindowSame(): void
361+
{
362+
$set = Set::of(1, 2, 3, 4, 5, 6);
363+
$result = $set->grouped(2);
364+
365+
self::assertEquals(3, $result->length());
366+
self::assertTrue(Set::of(1, 2)->equals($result->toArray()[0]));
367+
self::assertTrue(Set::of(3, 4)->equals($result->toArray()[1]));
368+
self::assertTrue(Set::of(5, 6)->equals($result->toArray()[2]));
369+
}
370+
371+
public function testSetGroupedWithRemainder(): void
372+
{
373+
$set = Set::of(1, 2, 3, 4, 5);
374+
$result = $set->grouped(2);
375+
376+
self::assertEquals(3, $result->length());
377+
self::assertTrue(Set::of(1, 2)->equals($result->toArray()[0]));
378+
self::assertTrue(Set::of(3, 4)->equals($result->toArray()[1]));
379+
self::assertTrue(Set::of(5)->equals($result->toArray()[2]));
380+
}
381+
382+
public function testSetGroupedSingleElement(): void
383+
{
384+
$set = Set::of(1, 2, 3);
385+
$result = $set->grouped(1);
386+
387+
self::assertEquals(3, $result->length());
388+
self::assertTrue(Set::of(1)->equals($result->toArray()[0]));
389+
self::assertTrue(Set::of(2)->equals($result->toArray()[1]));
390+
self::assertTrue(Set::of(3)->equals($result->toArray()[2]));
391+
}
392+
393+
public function testSetSlidingBehavesLikeGroupedWhenStepEqualsSize(): void
394+
{
395+
$set = Set::of(1, 2, 3, 4, 5, 6, 7, 8, 9);
396+
$slidingResult = $set->sliding(3, 3);
397+
$groupedResult = $set->grouped(3);
398+
399+
self::assertEquals($groupedResult->length(), $slidingResult->length());
400+
self::assertTrue(Set::of(1, 2, 3)->equals($slidingResult->toArray()[0]));
401+
self::assertTrue(Set::of(4, 5, 6)->equals($slidingResult->toArray()[1]));
402+
self::assertTrue(Set::of(7, 8, 9)->equals($slidingResult->toArray()[2]));
403+
404+
self::assertTrue($slidingResult->equals($groupedResult));
405+
}
406+
407+
public function testSetSlidingBehavesLikeGroupedWhenStepEqualsSizeForDifferentLastWindow(): void
408+
{
409+
$set = Set::of(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11);
410+
$slidingResult = $set->sliding(3, 3);
411+
$groupedResult = $set->grouped(3);
412+
413+
self::assertEquals($groupedResult->length(), $slidingResult->length());
414+
self::assertTrue(Set::of(1, 2, 3)->equals($slidingResult->toArray()[0]));
415+
self::assertTrue(Set::of(4, 5, 6)->equals($slidingResult->toArray()[1]));
416+
self::assertTrue(Set::of(7, 8, 9)->equals($slidingResult->toArray()[2]));
417+
self::assertTrue(Set::of(10, 11)->equals($slidingResult->toArray()[3]));
418+
419+
self::assertTrue($slidingResult->equals($groupedResult));
420+
}
421+
422+
public function testSetGroupedLargerSize(): void
423+
{
424+
$set = Set::of(1, 2);
425+
$result = $set->grouped(4);
426+
427+
self::assertEquals(1, $result->length());
428+
self::assertTrue(Set::of(1, 2)->equals($result->toArray()[0]));
429+
}
287430
}

0 commit comments

Comments
 (0)