Skip to content

Commit 886f171

Browse files
test at_most, exactly
1 parent bcd41f8 commit 886f171

File tree

7 files changed

+288
-31
lines changed

7 files changed

+288
-31
lines changed

composer.json

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,8 @@
3232
"src/Contains.php",
3333
"src/All.php",
3434
"src/AtLeast.php",
35+
"src/AtMost.php",
36+
"src/Exactly.php",
3537
"src/Add.php",
3638
"src/Set.php",
3739
"src/Pipe.php",

src/AtMost.php

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
<?php
2+
declare(strict_types=1);
3+
4+
namespace BrenoRoosevelt;
5+
6+
/**
7+
* Evaluates whether <b>at most n</b> elements match the specification
8+
*
9+
* @param int $n The number to check
10+
* @param iterable $items The collection
11+
* @param callable $callback Callable must return a boolean
12+
* @param int $mode [optional] <p>
13+
* Flag determining what arguments are sent to <i>callback</i>:
14+
* </p><ul>
15+
* <li>
16+
* <b>CALLBACK_USE_VALUE</b> - <b>default</b> pass value as the only argument
17+
* </li>
18+
* <li>
19+
* <b>CALLBACK_USE_KEY</b> - pass key as the only argument
20+
* to <i>callback</i> instead of the value</span>
21+
* </li>
22+
* <li>
23+
* <b>CALLBACK_USE_BOTH</b> - pass both value and key as
24+
* arguments to <i>callback</i></span>
25+
* </li>
26+
* </ul>
27+
* @return bool
28+
*/
29+
function at_most(int $n, iterable $items, callable $callback, int $mode = CALLBACK_USE_VALUE): bool
30+
{
31+
$count = 0;
32+
foreach ($items as $key => $value) {
33+
if (true === call_user_func_array($callback, __args($mode, $key, $value))) {
34+
$count++;
35+
if ($count > $n) {
36+
return false;
37+
}
38+
}
39+
}
40+
41+
return $count <= $n;
42+
}

src/Exactly.php

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
<?php
2+
declare(strict_types=1);
3+
4+
namespace BrenoRoosevelt;
5+
6+
/**
7+
* Evaluates whether <b>exactly n</b> elements match the specification
8+
*
9+
* @param int $n The number to check
10+
* @param iterable $items The collection
11+
* @param callable $callback Callable must return a boolean
12+
* @param int $mode [optional] <p>
13+
* Flag determining what arguments are sent to <i>callback</i>:
14+
* </p><ul>
15+
* <li>
16+
* <b>CALLBACK_USE_VALUE</b> - <b>default</b> pass value as the only argument
17+
* </li>
18+
* <li>
19+
* <b>CALLBACK_USE_KEY</b> - pass key as the only argument
20+
* to <i>callback</i> instead of the value</span>
21+
* </li>
22+
* <li>
23+
* <b>CALLBACK_USE_BOTH</b> - pass both value and key as
24+
* arguments to <i>callback</i></span>
25+
* </li>
26+
* </ul>
27+
* @return bool
28+
*/
29+
function exactly(int $n, iterable $items, callable $callback, int $mode = CALLBACK_USE_VALUE): bool
30+
{
31+
$count = 0;
32+
foreach ($items as $key => $value) {
33+
if (true === call_user_func_array($callback, __args($mode, $key, $value))) {
34+
$count++;
35+
if ($count > $n) {
36+
return false;
37+
}
38+
}
39+
}
40+
41+
return $count === $n;
42+
}

src/array_functions.php

Lines changed: 0 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -13,36 +13,6 @@ function none(iterable $items, callable $callback, int $mode = 0): bool
1313
return ! some($items, $callback, $mode);
1414
}
1515

16-
function at_most(int $n, iterable $items, callable $callback, int $mode = CALLBACK_USE_VALUE): bool
17-
{
18-
$count = 0;
19-
foreach ($items as $key => $value) {
20-
if (true === call_user_func_array($callback, __args($mode, $key, $value))) {
21-
$count++;
22-
if ($count > $n) {
23-
return false;
24-
}
25-
}
26-
}
27-
28-
return $count <= $n;
29-
}
30-
31-
function exactly(int $n, iterable $items, callable $callback, int $mode = CALLBACK_USE_VALUE): bool
32-
{
33-
$count = 0;
34-
foreach ($items as $key => $value) {
35-
if (true === call_user_func_array($callback, __args($mode, $key, $value))) {
36-
$count++;
37-
if ($count > $n) {
38-
return false;
39-
}
40-
}
41-
}
42-
43-
return $count === $n;
44-
}
45-
4616
function first(iterable $items, callable $callback, $default = null, int $mode = CALLBACK_USE_VALUE)
4717
{
4818
foreach ($items as $key => $value) {

tests/AtLeastTest.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ public function atLeastProvider(): array
1515
{
1616
return [
1717
'case_1' => [
18-
0,
18+
0, // n
1919
['a', 'b', 'c'], // collection
2020
fn($el) => false, // callback
2121
CALLBACK_USE_VALUE, // mode

tests/AtMostTest.php

Lines changed: 97 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,97 @@
1+
<?php
2+
declare(strict_types=1);
3+
4+
namespace BrenoRoosevelt\Tests;
5+
6+
use PHPUnit\Framework\TestCase;
7+
use function BrenoRoosevelt\at_most;
8+
use const BrenoRoosevelt\CALLBACK_USE_BOTH;
9+
use const BrenoRoosevelt\CALLBACK_USE_KEY;
10+
use const BrenoRoosevelt\CALLBACK_USE_VALUE;
11+
12+
class AtMostTest extends TestCase
13+
{
14+
public function atMostProvider(): array
15+
{
16+
return [
17+
'case_1' => [
18+
0, // n
19+
['a', 'b', 'c'], // collection
20+
fn($el) => false, // callback
21+
CALLBACK_USE_VALUE, // mode
22+
true, // expected
23+
],
24+
'case_2' => [
25+
4,
26+
['a', 'b', 'c'],
27+
fn($el) => true,
28+
CALLBACK_USE_VALUE,
29+
true,
30+
],
31+
'case_3' => [
32+
1,
33+
[],
34+
fn($el) => true,
35+
CALLBACK_USE_VALUE,
36+
true,
37+
],
38+
'case_3_1' => [
39+
0,
40+
[],
41+
fn($el) => true,
42+
CALLBACK_USE_VALUE,
43+
true,
44+
],
45+
'case_3_2' => [
46+
-1,
47+
[],
48+
fn($el) => true,
49+
CALLBACK_USE_VALUE,
50+
false,
51+
],
52+
'case_4' => [
53+
1,
54+
[1, 2, 3, 4],
55+
fn($el) => $el % 2 === 0,
56+
CALLBACK_USE_VALUE,
57+
false,
58+
],
59+
'case_5' => [
60+
4,
61+
[1, 2, 3, 4],
62+
fn($el) => $el % 2 === 0,
63+
CALLBACK_USE_VALUE,
64+
true,
65+
],
66+
'case_6' => [
67+
3,
68+
[1, 2, 3, 4],
69+
fn($key) => is_integer($key),
70+
CALLBACK_USE_KEY,
71+
false,
72+
],
73+
'case_7' => [
74+
0,
75+
['a' => 1, 'b' => 2, 'c' => 3, 4],
76+
fn($v, $key) => is_integer($key) && is_integer($v),
77+
CALLBACK_USE_BOTH,
78+
false,
79+
]
80+
];
81+
}
82+
83+
/**
84+
* @param int $n
85+
* @param iterable $items
86+
* @param callable $callback
87+
* @param int $mode
88+
* @param bool $expected
89+
* @return void
90+
* @dataProvider atMostProvider
91+
*/
92+
public function testAtMost(int $n, iterable $items, callable $callback, int $mode, bool $expected): void
93+
{
94+
$actual = at_most($n, $items, $callback, $mode);
95+
$this->assertEquals($expected, $actual);
96+
}
97+
}

tests/ExactlyTest.php

Lines changed: 104 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,104 @@
1+
<?php
2+
declare(strict_types=1);
3+
4+
namespace BrenoRoosevelt\Tests;
5+
6+
use PHPUnit\Framework\TestCase;
7+
use function BrenoRoosevelt\exactly;
8+
use const BrenoRoosevelt\CALLBACK_USE_BOTH;
9+
use const BrenoRoosevelt\CALLBACK_USE_KEY;
10+
use const BrenoRoosevelt\CALLBACK_USE_VALUE;
11+
12+
class ExactlyTest extends TestCase
13+
{
14+
public function exactlyProvider(): array
15+
{
16+
return [
17+
'case_1' => [
18+
0, // n
19+
['a', 'b', 'c'], // collection
20+
fn($el) => false, // callback
21+
CALLBACK_USE_VALUE, // mode
22+
true, // expected
23+
],
24+
'case_2' => [
25+
3,
26+
['a', 'b', 'c'],
27+
fn($el) => true,
28+
CALLBACK_USE_VALUE,
29+
true,
30+
],
31+
'case_3' => [
32+
1,
33+
[],
34+
fn($el) => true,
35+
CALLBACK_USE_VALUE,
36+
false,
37+
],
38+
'case_3_1' => [
39+
0,
40+
[],
41+
fn($el) => true,
42+
CALLBACK_USE_VALUE,
43+
true,
44+
],
45+
'case_3_2' => [
46+
-1,
47+
[],
48+
fn($el) => true,
49+
CALLBACK_USE_VALUE,
50+
false,
51+
],
52+
'case_4' => [
53+
1,
54+
[1, 2, 3, 4],
55+
fn($el) => $el % 2 === 0,
56+
CALLBACK_USE_VALUE,
57+
false,
58+
],
59+
'case_5' => [
60+
2,
61+
[1, 2, 3, 4],
62+
fn($el) => $el % 2 === 0,
63+
CALLBACK_USE_VALUE,
64+
true,
65+
],
66+
'case_6' => [
67+
3,
68+
[1, 2, 3, 4],
69+
fn($key) => is_integer($key),
70+
CALLBACK_USE_KEY,
71+
false,
72+
],
73+
'case_6_1' => [
74+
1,
75+
[1, 2, 3, 4, 'a' => 5],
76+
fn($key) => is_string($key),
77+
CALLBACK_USE_KEY,
78+
true,
79+
],
80+
'case_7' => [
81+
1,
82+
['a' => 1, 'b' => 2, 'c' => 3, 4],
83+
fn($v, $key) => is_integer($key) && is_integer($v),
84+
CALLBACK_USE_BOTH,
85+
true,
86+
]
87+
];
88+
}
89+
90+
/**
91+
* @param int $n
92+
* @param iterable $items
93+
* @param callable $callback
94+
* @param int $mode
95+
* @param bool $expected
96+
* @return void
97+
* @dataProvider exactlyProvider
98+
*/
99+
public function testExactly(int $n, iterable $items, callable $callback, int $mode, bool $expected): void
100+
{
101+
$actual = exactly($n, $items, $callback, $mode);
102+
$this->assertEquals($expected, $actual);
103+
}
104+
}

0 commit comments

Comments
 (0)