Skip to content

Commit

Permalink
Methods match() and matchWith() added and tested.
Browse files Browse the repository at this point in the history
  • Loading branch information
Smoren committed Mar 18, 2024
1 parent 60e7cb4 commit ad87d02
Show file tree
Hide file tree
Showing 3 changed files with 113 additions and 3 deletions.
13 changes: 13 additions & 0 deletions src/Interfaces/ArrayViewInterface.php
Original file line number Diff line number Diff line change
Expand Up @@ -80,9 +80,22 @@ public function filter(callable $predicate): ArrayViewInterface;
* @param callable(T, int): bool $predicate Function that returns a boolean value for each element.
*
* @return MaskSelectorInterface Boolean mask for selecting elements that satisfy the predicate.
*
* @see ArrayViewInterface::match() Full synonim.
*/
public function is(callable $predicate): MaskSelectorInterface;

/**
* Checks if all elements in the view satisfy a given predicate function.
*
* @param callable(T, int): bool $predicate Function that returns a boolean value for each element.
*
* @return MaskSelectorInterface Boolean mask for selecting elements that satisfy the predicate.
*
* @see ArrayViewInterface::is() Full synonim.
*/
public function match(callable $predicate): MaskSelectorInterface;

/**
* Compares the elements of the current ArrayView instance with another array or ArrayView
* using the provided comparator function.
Expand Down
33 changes: 33 additions & 0 deletions src/Views/ArrayView.php
Original file line number Diff line number Diff line change
Expand Up @@ -226,13 +226,44 @@ public function filter(callable $predicate): ArrayViewInterface
* @param callable(T, int): bool $predicate Function that returns a boolean value for each element.
*
* @return MaskSelector Boolean mask for selecting elements that satisfy the predicate.
*
* @see ArrayViewInterface::match() Full synonim.
*/
public function is(callable $predicate): MaskSelectorInterface
{
$data = $this->toArray();
return new MaskSelector(array_map($predicate, $data, array_keys($data)));
}

/**
* Checks if all elements in the view satisfy a given predicate function.
*
* ##### Example
* ```php
* $source = [1, 2, 3, 4, 5, 6];
* $view = ArrayView::toView($source);
*
* $mask = $view->is(fn ($x) => $x % 2 === 0);
* $mask->getValue(); // [false, true, false, true, false, true]
*
* $view->subview($mask)->toArray(); // [2, 4, 6]
* $view[$mask]; // [2, 4, 6]
*
* $view[$mask] = [20, 40, 60];
* $source; // [1, 20, 3, 40, 5, 60]
* ```
*
* @param callable(T, int): bool $predicate Function that returns a boolean value for each element.
*
* @return MaskSelector Boolean mask for selecting elements that satisfy the predicate.
*
* @see ArrayView::match() Full synonim.
*/
public function match(callable $predicate): MaskSelectorInterface
{
return $this->is($predicate);
}

/**
* Compares the elements of the current ArrayView instance with another array or ArrayView
* using the provided comparator function.
Expand All @@ -246,6 +277,8 @@ public function is(callable $predicate): MaskSelectorInterface
*
* @throws ValueError if the $data is not sequential array.
* @throws SizeError if size of $data not equals to size of the view.
*
* @see ArrayView::is() Full synonim.
*/
public function matchWith($data, callable $comparator): MaskSelectorInterface
{
Expand Down
70 changes: 67 additions & 3 deletions tests/unit/ArrayView/ReadTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -60,23 +60,46 @@ public function testReadPipe(array $source, array $selectors, array $expected)
}

/**
* @dataProvider dataProviderForIsAndFilter
* @dataProvider dataProviderForMatchAndFilter
*/
public function testIsAndFilter(array $source, callable $predicate, array $expectedMask, array $expectedArray)
public function testMatchAndFilter(array $source, callable $predicate, array $expectedMask, array $expectedArray)
{
// Given
$view = ArrayView::toView($source);

// When
$boolMask = $view->is($predicate);
$boolMaskCopy = $view->match($predicate);
$filtered = $view->filter($predicate);

// Then
$this->assertSame($expectedMask, $boolMask->getValue());
$this->assertSame($expectedMask, $boolMaskCopy->getValue());
$this->assertSame($expectedArray, $view->subview($boolMask)->toArray());
$this->assertSame($expectedArray, $filtered->toArray());
}

/**
* @dataProvider dataProviderForMatchWith
*/
public function testMatchWith(
array $source,
array $another,
callable $comparator,
array $expectedMask,
array $expectedArray
) {
// Given
$view = ArrayView::toView($source);

// When
$boolMask = $view->matchWith($another, $comparator);

// Then
$this->assertSame($expectedMask, $boolMask->getValue());
$this->assertSame($expectedArray, $view->subview($boolMask)->toArray());
}

public function dataProviderForArrayRead(): array
{
return [
Expand Down Expand Up @@ -378,7 +401,7 @@ public function dataProviderForReadPipe(): array
];
}

public function dataProviderForIsAndFilter(): array
public function dataProviderForMatchAndFilter(): array
{
return [
[
Expand Down Expand Up @@ -407,4 +430,45 @@ public function dataProviderForIsAndFilter(): array
],
];
}

public function dataProviderForMatchWith(): array
{
return [
[
[],
[],
fn (int $lhs, int $rhs) => $rhs > $lhs,
[],
[],
],
[
[1],
[1],
fn (int $lhs, int $rhs) => $rhs > $lhs,
[false],
[],
],
[
[1],
[2],
fn (int $lhs, int $rhs) => $rhs > $lhs,
[true],
[1],
],
[
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10],
[1, 22, 3, 4, 5, 6, 7, 8, 99, 10],
fn (int $lhs, int $rhs) => $rhs > $lhs,
[false, true, false, false, false, false, false, false, true, false],
[2, 9],
],
[
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10],
[1, 22, 3, 4, 5, 6, 7, 8, 99, 10],
fn (int $lhs, int $rhs) => $lhs >= $rhs,
[true, false, true, true, true, true, true, true, false, true],
[1, 3, 4, 5, 6, 7, 8, 10],
],
];
}
}

0 comments on commit ad87d02

Please sign in to comment.