Page Menu
Home
DevCentral
Search
Configure Global Search
Log In
Files
F3767793
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Award Token
Flag For Later
Size
31 KB
Referenced Files
None
Subscribers
None
View Options
diff --git a/omnitools/src/Collections/WithCollection.php b/omnitools/src/Collections/WithCollection.php
index 3b7c3ee..45baae3 100644
--- a/omnitools/src/Collections/WithCollection.php
+++ b/omnitools/src/Collections/WithCollection.php
@@ -1,27 +1,100 @@
<?php
namespace Keruald\OmniTools\Collections;
+use Keruald\OmniTools\Reflection\CallableElement;
+
+use InvalidArgumentException;
use OutOfRangeException;
trait WithCollection {
abstract function count () : int;
abstract function toArray() : array;
public function first () : mixed {
foreach ($this->toArray() as $item) {
return $item;
}
throw new OutOfRangeException("The collection is empty.");
}
public function firstOr (mixed $default) : mixed {
return match ($this->count()) {
0 => $default,
default => $this->first(),
};
}
+ ///
+ /// HOF
+ ///
+
+ /**
+ * Determines if at least an element of the collection satisfies a condition.
+ *
+ * The execution of callbacks stop after a callable returned true.
+ *
+ * @param callable $callable A method returning a boolean with key and value
+ * or only value as arguments.
+ *
+ * @return bool True if callback is true for at least one of the elements
+ * @throws \ReflectionException if the callable does not exist.
+ */
+ public function any (callable $callable) : bool {
+ $argc = (new CallableElement($callable))->countArguments();
+ $items = $this->toArray();
+
+ foreach ($items as $key => $value) {
+ $result = match($argc) {
+ 0 => throw new InvalidArgumentException(self::CB_ZERO_ARG),
+ 1 => $callable($value),
+ default => $callable($key, $value),
+ };
+
+ // PHP standard or extensions functions can sometimes throw
+ // mixed result, for example true or a constant. Any other
+ // result than the boolean true is interpreted as falsy.
+ if ($result === true) {
+ return true;
+ }
+ }
+
+ return false;
+ }
+
+ /**
+ * Determines if all elements of the collection satisfies a condition.
+ *
+ * The execution of callbacks stop after a callable returned false.
+ *
+ * @param callable $callable A method returning a boolean with key and value
+ * or only value as arguments.
+ *
+ * @return bool True if callback is true for all the elements
+ * @throws \ReflectionException if the callable does not exist.
+ */
+ public function all (callable $callable) : bool {
+ $argc = (new CallableElement($callable))->countArguments();
+ $items = $this->toArray();
+
+ foreach ($items as $key => $value) {
+ $result = match($argc) {
+ 0 => throw new InvalidArgumentException(self::CB_ZERO_ARG),
+ 1 => $callable($value),
+ default => $callable($key, $value),
+ };
+
+ // PHP standard or extensions functions can sometimes throw
+ // mixed result, for example true or a constant. Any other
+ // result than the boolean true is interpreted as falsy.
+ if ($result !== true) {
+ return false;
+ }
+ }
+
+ return true;
+ }
+
}
diff --git a/omnitools/tests/Collections/HashMapTest.php b/omnitools/tests/Collections/HashMapTest.php
index 9529d66..4d39415 100644
--- a/omnitools/tests/Collections/HashMapTest.php
+++ b/omnitools/tests/Collections/HashMapTest.php
@@ -1,528 +1,556 @@
<?php
namespace Keruald\OmniTools\Tests\Collections;
use Keruald\OmniTools\Collections\BitsVector;
use Keruald\OmniTools\Collections\HashMap;
use PHPUnit\Framework\Attributes\DataProvider;
use PHPUnit\Framework\TestCase;
use InvalidArgumentException;
use IteratorAggregate;
use OutOfRangeException;
use Traversable;
class HashMapTest extends TestCase {
///
/// Test set up
///
private HashMap $map;
const MAP_CONTENT = [
// Some sci-fi civilizations and author
"The Culture" => "Iain Banks",
"Radchaai Empire" => "Ann Leckie",
"Barrayar" => "Lois McMaster Bujold",
"Hainish" => "Ursula K. Le Guin",
];
protected function setUp () : void {
$this->map = new HashMap(self::MAP_CONTENT);
}
///
/// Constructors
///
public function testConstructorWithArray () {
$this->assertSame(self::MAP_CONTENT, $this->map->toArray());
}
public function testConstructorWithTraversable () {
$expected = [
"color" => "blue",
"material" => "glass",
"shape" => "sphere",
];
$iterable = new class implements IteratorAggregate {
function getIterator () : Traversable {
yield "color" => "blue";
yield "material" => "glass";
yield "shape" => "sphere";
}
};
$map = new HashMap($iterable);
$this->assertSame($expected, $map->toArray());
}
public static function provideDeepArrays() : iterable {
yield [self::MAP_CONTENT, self::MAP_CONTENT];
yield [[], []];
yield [null, []];
$caps = new \stdClass;
$caps->color = "red";
$caps->logo = "HCKR";
yield [$caps, [
"color" => "red",
"logo" => "HCKR",
]];
$sizedCaps = clone $caps;
$sizedCaps->size = new \stdClass;
$sizedCaps->size->h = 8;
$sizedCaps->size->r = 20;
yield [$sizedCaps, [
"color" => "red",
"logo" => "HCKR",
"size" => ["h" => 8, "r" => 20],
]];
}
#[DataProvider('provideDeepArrays')]
public function testFrom($from, array $expected) : void {
$map = HashMap::from($from);
$this->assertEquals($expected, $map->toArray());
}
///
/// Getters and setters
///
public function testGet () {
$this->assertSame("Iain Banks", $this->map->get("The Culture"));
}
public function testGetWhenKeyIsNotFound () {
$this->expectException(InvalidArgumentException::class);
$this->map->get("Quuxians");
}
public function testGetOr () {
$actual = $this->map
->getOr("The Culture", "Another author");
$this->assertSame("Iain Banks", $actual);
}
public function testGetOrWhenKeyIsNotFound () {
$actual = $this->map
->getOr("Quuxians", "Another author");
$this->assertSame("Another author", $actual);
}
public function testSetWithNewKey () {
$this->map->set("Thélème", "François Rabelais");
$this->assertSame("François Rabelais",
$this->map->get("Thélème"));
}
public function testSetWithExistingKey () {
$this->map->set("The Culture", "Iain M. Banks");
$this->assertSame("Iain M. Banks",
$this->map->get("The Culture"));
}
public function testUnset() {
$this->map->unset("The Culture");
$this->assertFalse($this->map->contains("Iain Banks"));
}
public function testUnsetNotExistingKey() {
$this->map->unset("Not existing");
$this->assertEquals(4, $this->map->count());
}
public function testHas () {
$this->assertTrue($this->map->has("The Culture"));
$this->assertFalse($this->map->has("Not existing key"));
}
public function testContains () {
$this->assertTrue($this->map->contains("Iain Banks"));
$this->assertFalse($this->map->contains("Not existing value"));
}
///
/// Collection method
///
public function testCount () {
$this->assertSame(4, $this->map->count());
}
public function testClear () {
$this->map->clear();
$this->assertSame(0, $this->map->count());
}
public function testIsEmpty () : void {
$this->map->clear();
$this->assertTrue($this->map->isEmpty());
}
public function testMerge () {
$iterable = [
"The Culture" => "Iain M. Banks", // existing key
"Thélème" => "François Rabelais", // new key
];
$expected = [
// The original map
"The Culture" => "Iain Banks", // Old value should be kept
"Radchaai Empire" => "Ann Leckie",
"Barrayar" => "Lois McMaster Bujold",
"Hainish" => "Ursula K. Le Guin",
// The entries with a new key
"Thélème" => "François Rabelais",
];
$this->map->merge($iterable);
$this->assertSame($expected, $this->map->toArray());
}
public function testUpdate () {
$iterable = [
"The Culture" => "Iain M. Banks", // existing key
"Thélème" => "François Rabelais", // new key
];
$expected = [
// The original map
"The Culture" => "Iain M. Banks", // Old value should be updated
"Radchaai Empire" => "Ann Leckie",
"Barrayar" => "Lois McMaster Bujold",
"Hainish" => "Ursula K. Le Guin",
// The entries with a new key
"Thélème" => "François Rabelais",
];
$this->map->update($iterable);
$this->assertSame($expected, $this->map->toArray());
}
public function testToArray () {
$this->assertEquals(self::MAP_CONTENT, $this->map->toArray());
}
///
/// High order functions
///
public function testMap () {
$callback = function ($value) {
return "author='" . $value . "'";
};
$expected = [
"The Culture" => "author='Iain Banks'",
"Radchaai Empire" => "author='Ann Leckie'",
"Barrayar" => "author='Lois McMaster Bujold'",
"Hainish" => "author='Ursula K. Le Guin'",
];
$actual = $this->map->map($callback)->toArray();
$this->assertEquals($expected, $actual);
}
public function testMapKeys () {
$callback = function ($key) {
return "civ::" . $key;
};
$expected = [
// Some sci-fi civilizations and author
"civ::The Culture" => "Iain Banks",
"civ::Radchaai Empire" => "Ann Leckie",
"civ::Barrayar" => "Lois McMaster Bujold",
"civ::Hainish" => "Ursula K. Le Guin",
];
$actual = $this->map->mapKeys($callback)->toArray();
$this->assertEquals($expected, $actual);
}
public function testMapKeysAndValues () : void {
$callback = function ($civilization, $author) {
return [$author[0], "$author, $civilization"];
};
$expected = [
// Some sci-fi civilizations and author
"I" => "Iain Banks, The Culture",
"A" => "Ann Leckie, Radchaai Empire",
"L" => "Lois McMaster Bujold, Barrayar",
"U"=> "Ursula K. Le Guin, Hainish",
];
$actual = $this->map->mapValuesAndKeys($callback)->toArray();
$this->assertEquals($expected, $actual);
}
public function testMapKeysAndValuesForVectors () : void {
$callback = function ($author) {
return [$author[0], "author:" . $author];
};
$expected = [
// Some sci-fi civilizations and author
"I" => "author:Iain Banks",
"A" => "author:Ann Leckie",
"L" => "author:Lois McMaster Bujold",
"U" => "author:Ursula K. Le Guin",
];
$actual = $this->map->mapValuesAndKeys($callback)->toArray();
$this->assertEquals($expected, $actual);
}
public function testMapKeysAndValuesWithCallbackWithoutArgument() : void {
$this->expectException(InvalidArgumentException::class);
$callback = function () {};
$this->map->mapValuesAndKeys($callback);
}
public function testFlatMap(): void {
$callback = function ($key, $value) {
$items = explode(" ", $value);
foreach ($items as $item) {
yield $item => $key;
}
};
$expected = [
"Iain" => "The Culture",
"Banks" => "The Culture",
"Ann" => "Radchaai Empire",
"Leckie" => "Radchaai Empire",
"Lois" => "Barrayar",
"McMaster" => "Barrayar",
"Bujold" => "Barrayar",
"Ursula"=> "Hainish",
"K."=> "Hainish",
"Le"=> "Hainish",
"Guin"=> "Hainish",
];
$actual = $this->map->flatMap($callback)->toArray();
$this->assertEquals($expected, $actual);
}
public function testFlatMapForVectors() : void {
$callback = function ($value) {
$items = explode(" ", $value);
foreach ($items as $item) {
yield $item => $value;
}
};
$expected = [
"Iain" => "Iain Banks",
"Banks" => "Iain Banks",
"Ann" => "Ann Leckie",
"Leckie" => "Ann Leckie",
"Lois" => "Lois McMaster Bujold",
"McMaster" => "Lois McMaster Bujold",
"Bujold" => "Lois McMaster Bujold",
"Ursula"=> "Ursula K. Le Guin",
"K."=> "Ursula K. Le Guin",
"Le"=> "Ursula K. Le Guin",
"Guin"=> "Ursula K. Le Guin",
];
$actual = $this->map->flatMap($callback)->toArray();
$this->assertEquals($expected, $actual);
}
public function testFlatMapWithCallbackWithoutArgument() : void {
$this->expectException(InvalidArgumentException::class);
$callback = function () {};
$this->map->flatMap($callback);
}
public function testMapToVector() : void {
$expected = [
"The Culture by Iain Banks",
"Radchaai Empire by Ann Leckie",
"Barrayar by Lois McMaster Bujold",
"Hainish by Ursula K. Le Guin",
];
$fn = fn($key, $value) => "$key by $value";
$this->assertEquals($expected, $this->map->mapToVector($fn)->toArray());
}
public function testMapToVectorWithOnlyValueParameter() : void {
$expected = [
"Author: Iain Banks",
"Author: Ann Leckie",
"Author: Lois McMaster Bujold",
"Author: Ursula K. Le Guin",
];
$fn = fn($value) => "Author: $value";
$this->assertEquals($expected, $this->map->mapToVector($fn)->toArray());
}
public function testMapToVectorWithoutParameter() : void {
$this->expectException(InvalidArgumentException::class);
$fn = fn() => "";
$this->map->mapToVector($fn);
}
public function testFilter () {
// Let's filter to keep names with 3 parts or more
$callback = function ($value) : bool {
return str_word_count($value) > 2;
};
$expected = [
// Some sci-fi civilizations and author
"Barrayar" => "Lois McMaster Bujold",
"Hainish" => "Ursula K. Le Guin",
];
$actual = $this->map->filter($callback)->toArray();
$this->assertEquals($expected, $actual);
}
public function testFilterWithKeyValueCallback () {
// Let's find civilization AND author with e inside
$expected = [
// Some sci-fi civilizations and author
"Radchaai Empire" => "Ann Leckie",
];
$callback = function ($key, $value) : bool {
return str_contains($key, "e") && str_contains($value, "e");
};
$actual = $this->map->filter($callback)->toArray();
$this->assertEquals($expected, $actual);
}
public function testFilterWithCallbackWithoutArgument() {
$this->expectException(InvalidArgumentException::class);
$callback = function () : bool { // No argument
return true;
};
$this->map->filter($callback);
}
public function testFilterKeys () {
// Let's filter to keep short civilization names
$callback = function ($key) : bool {
return str_word_count($key) == 1;
};
$expected = [
// Some sci-fi civilizations and author
"Barrayar" => "Lois McMaster Bujold",
"Hainish" => "Ursula K. Le Guin",
];
$actual = $this->map->filterKeys($callback)->toArray();
$this->assertEquals($expected, $actual);
}
+ ///
+ /// HOF methods - WithCollection
+ ///
+
+ public function testAny () : void {
+ $author_is_Iain_Banks = fn($author) => $author === "Iain Banks";
+
+ $this->assertTrue($this->map->any($author_is_Iain_Banks));
+ }
+
+ public function testAnyWithAllFalseValues () : void {
+ $author_is_Isaac_Asimov = fn($author) => $author === "Isaac Asimov";
+
+ $this->assertFalse($this->map->any($author_is_Isaac_Asimov));
+ }
+
+ public function testAll () : void {
+ $author_contains_space = fn($author) => str_contains($author, " ");
+
+ $this->assertTrue($this->map->all($author_contains_space));
+ }
+
+ public function testAllWithFalseValue () : void {
+ $author_is_Iain_Banks = fn($author) => $author === "Iain Banks";
+
+ $this->assertFalse($this->map->all($author_is_Iain_Banks));
+ }
+
///
/// ArrayAccess
///
public function testOffsetExists () : void {
$this->assertTrue(isset($this->map["The Culture"]));
$this->assertFalse(isset($this->map["Not existing"]));
}
public function testOffsetSetWithoutOffset () : void {
$this->expectException(InvalidArgumentException::class);
$this->map[] = "Another Author";
}
public function testOffsetSet () : void {
$this->map["The Culture"] = "Iain M. Banks";
$this->assertEquals("Iain M. Banks", $this->map["The Culture"]);
}
public function testOffsetUnset () : void {
unset($this->map["Barrayar"]);
$expected = [
"The Culture" => "Iain Banks",
"Radchaai Empire" => "Ann Leckie",
// "Barrayar" => "Lois McMaster Bujold", UNSET ENTRY
"Hainish" => "Ursula K. Le Guin",
];
$this->assertEquals($expected, $this->map->toArray());
}
///
/// IteratorAggregate
///
public function testGetIterator () : void {
$this->assertEquals(self::MAP_CONTENT, iterator_to_array($this->map));
}
///
/// WithCollection trait
///
public function testFirst () : void {
$this->assertEquals("Iain Banks", $this->map->first());
}
public function testFirstWhenEmpty () : void {
$map = new HashMap();
$this->expectException(OutOfRangeException::class);
$map->first();
}
public function testFirstOr () : void {
$bits = BitsVector::new(4);
$bits[2] = 1;
$this->assertEquals("Iain Banks", $this->map->firstOr("Anonymous"));
}
public function testFirstOrWhenEmpty () : void {
$map = new HashMap();
$this->assertEquals("Anonymous", $map->firstOr("Anonymous"));
}
}
diff --git a/omnitools/tests/Collections/VectorTest.php b/omnitools/tests/Collections/VectorTest.php
index 49941b7..98883e9 100644
--- a/omnitools/tests/Collections/VectorTest.php
+++ b/omnitools/tests/Collections/VectorTest.php
@@ -1,432 +1,456 @@
<?php
declare(strict_types=1);
namespace Keruald\OmniTools\Tests\Collections;
use Keruald\OmniTools\Collections\BaseVector;
use Keruald\OmniTools\Collections\HashMap;
use Keruald\OmniTools\Collections\Vector;
use PHPUnit\Framework\Attributes\CoversClass;
use PHPUnit\Framework\Attributes\DataProvider;
use PHPUnit\Framework\TestCase;
use InvalidArgumentException;
use IteratorAggregate;
use OutOfRangeException;
use Traversable;
#[CoversClass(Vector::class)]
#[CoversClass(BaseVector::class)]
class VectorTest extends TestCase {
private Vector $vector;
protected function setUp () : void {
$this->vector = new Vector([1, 2, 3, 4, 5]);
}
public function testConstructorWithIterable () : void {
$iterable = new class implements IteratorAggregate {
public function getIterator () : Traversable {
yield 42;
yield 100;
}
};
$vector = new Vector($iterable);
$this->assertEquals([42, 100], $vector->toArray());
}
public function testFrom () : void {
$this->assertEquals([42, 100], Vector::from([42, 100])->toArray());
}
public function testGet () : void {
$vector = new Vector(["a", "b", "c"]);
$this->assertEquals("b", $vector->get(1));
}
public function testGetOverflow () : void {
$this->expectException(InvalidArgumentException::class);
$this->vector->get(800);
}
public function testGetOr () : void {
$vector = new Vector(["a", "b", "c"]);
$this->assertEquals("X", $vector->getOr(800, "X"));
}
public function testSet () : void {
$vector = new Vector(["a", "b", "c"]);
$vector->set(1, "x"); // should replace "b"
$this->assertEquals(["a", "x", "c"], $vector->toArray());
}
public function testContains () : void {
$this->assertTrue($this->vector->contains(2));
$this->assertFalse($this->vector->contains(666));
}
public function testCount () : void {
$this->assertEquals(5, $this->vector->count());
$this->assertEquals(0, (new Vector)->count());
}
public function testClear () : void {
$this->vector->clear();
$this->assertEquals(0, $this->vector->count());
}
public function testIsEmpty () : void {
$this->vector->clear();
$this->assertTrue($this->vector->isEmpty());
}
public function testPush () : void {
$this->vector->push(6);
$this->assertEquals([1, 2, 3, 4, 5, 6], $this->vector->toArray());
}
public function testAppend () : void {
$this->vector->append([6, 7, 8]);
$this->assertEquals([1, 2, 3, 4, 5, 6, 7 ,8], $this->vector->toArray());
}
public function testUpdate () : void {
$this->vector->update([5, 5, 5, 6, 7, 8]); // 5 already exists
$this->assertEquals([1, 2, 3, 4, 5, 6, 7 ,8], $this->vector->toArray());
}
public function testMap () : void {
$actual = $this->vector
->map(function ($x) { return $x * $x; })
->toArray();
$this->assertEquals([1, 4, 9, 16, 25], $actual);
}
public function testMapKeys () : void {
$vector = new Vector(["foo", "bar", "quux", "xizzy"]);
$filter = function ($key) {
return 0; // Let's collapse our array
};
$actual = $vector->mapKeys($filter)->toArray();
$this->assertEquals(["xizzy"], $actual);
}
public function testFlatMap () : void {
$expected = [
// Squares and cubes
1, 1,
4, 8,
9, 27,
16, 64,
25, 125
];
$callback = function ($n) {
yield $n * $n;
yield $n * $n * $n;
};
$actual = $this->vector->flatMap($callback)->toArray();
$this->assertEquals($expected, $actual);
}
public function testFlatMapWithKeyValueCallback() : void {
$vector = new Vector(["foo", "bar", "quux", "xizzy"]);
$callback = function (int $key, string $value) {
yield "$key::$value";
yield "$value ($key)";
};
$expected = [
"0::foo",
"foo (0)",
"1::bar",
"bar (1)",
"2::quux",
"quux (2)",
"3::xizzy",
"xizzy (3)",
];
$actual = $vector->flatMap($callback)->toArray();
$this->assertEquals($expected, $actual);
}
public function testFlatMapWithCallbackWithoutArgument() : void {
$this->expectException(InvalidArgumentException::class);
$callback = function () {};
$this->vector->flatMap($callback);
}
public function testMapToHashMap () : void {
$expected = [
1 => 1,
2 => 4,
3 => 9,
4 => 16,
5 => 25,
];
$fn = fn($value) => [$value, $value * $value];
$map = $this->vector->mapToHashMap($fn);
$this->assertInstanceOf(HashMap::class, $map);
$this->assertEquals($expected, $map->toArray());
}
public function testMapToHashMapWithCallbackWithoutArgument() : void {
$this->expectException(InvalidArgumentException::class);
$callback = function () {};
$this->vector->mapToHashMap($callback);
}
public function testMapToHashMapWithBadCallback () : void {
$this->expectException(InvalidArgumentException::class);
$callback = fn($key, $value) : bool => false; // not an array
$this->vector->mapToHashMap($callback);
}
public function testFilter () : void {
$vector = new Vector(["foo", "bar", "quux", "xizzy"]);
$filter = function ($item) {
return strlen($item) === 3; // Let's keep 3-letters words
};
$actual = $vector->filter($filter)->toArray();
$this->assertEquals(["foo", "bar"], $actual);
}
public function testFilterWithBadCallback () : void {
$this->expectException(InvalidArgumentException::class);
$badFilter = function () {};
$this->vector->filter($badFilter);
}
public function testFilterKeys () : void {
$filter = function ($key) {
return $key % 2 === 0; // Let's keep even indices
};
$actual = $this->vector
->filterKeys($filter)
->toArray();
$this->assertEquals([0, 2, 4], array_keys($actual));
}
+ public function testAny () : void {
+ $is_even = fn(int $item) : bool => $item % 2 === 0;
+
+ $this->assertTrue($this->vector->any($is_even));
+ }
+
+ public function testAnyWithAllFalseValues () : void {
+ $is_zero = fn(int $item) : bool => $item === 0;
+
+ $this->assertFalse($this->vector->any($is_zero));
+ }
+
+ public function testAll () : void {
+ $under_ten = fn(int $item) : bool => $item < 10;
+
+ $this->assertTrue($this->vector->all($under_ten));
+ }
+
+ public function testAllWithFalseValue () : void {
+ $is_even = fn(int $item) : bool => $item % 2 === 0;
+
+ $this->assertFalse($this->vector->all($is_even));
+ }
+
public function testChunk () : void {
$vector = new Vector([1, 2, 3, 4, 5, 6]);
$this->assertEquals(
[[1, 2], [3, 4], [5, 6]],
$vector->chunk(2)->toArray()
);
}
public function testSlice () : void {
$actual = $this->vector->slice(2, 3);
$this->assertEquals([3, 4, 5], $actual->toArray());
}
public function testImplode() : void {
$actual = (new Vector(["a", "b", "c"]))
->implode(".")
->__toString();
$this->assertEquals("a.b.c", $actual);
}
public function testImplodeWithoutDelimiter() : void {
$actual = (new Vector(["a", "b", "c"]))
->implode("")
->__toString();
$this->assertEquals("abc", $actual);
}
public function testExplode() : void {
$actual = Vector::explode(".", "a.b.c");
$this->assertEquals(["a", "b", "c"], $actual->toArray());
}
public function testExplodeWithoutDelimiter() : void {
$actual = Vector::explode("", "a.b.c");
$this->assertEquals(["a.b.c"], $actual->toArray());
}
///
/// n-grams
///
public function testBigrams() : void {
$expected = Vector::from([
[1, 2],
[2, 3],
[3, 4],
[4, 5],
]);
$this->assertEquals($expected, $this->vector->bigrams());
}
public function testTrigrams() : void {
$expected = Vector::from([
[1, 2, 3],
[2, 3, 4],
[3, 4, 5],
]);
$this->assertEquals($expected, $this->vector->trigrams());
}
public function testNgrams() : void {
$expected = Vector::from([
[1, 2, 3, 4],
[2, 3, 4, 5],
]);
$this->assertEquals($expected, $this->vector->ngrams(4));
}
public function testNgramsWithN1 () : void {
$expected = Vector::from([
[1],
[2],
[3],
[4],
[5],
]);
$this->assertEquals($expected, $this->vector->ngrams(1));
}
public static function provideLowN () : iterable {
yield [0];
yield [-1];
yield [PHP_INT_MIN];
}
#[DataProvider('provideLowN')]
public function testNgramsWithTooLowN ($n) : void {
$this->expectException(InvalidArgumentException::class);
$this->vector->ngrams($n);
}
public static function provideLargeN () : iterable {
yield [5];
yield [6];
yield [PHP_INT_MAX];
}
#[DataProvider('provideLargeN')]
public function testNgramsWithTooLargeN ($n) : void {
$expected = Vector::from([
[1, 2, 3, 4, 5],
]);
$this->assertEquals($expected, $this->vector->ngrams($n));
}
///
/// ArrayAccess
///
public function testArrayAccessFailsWithStringKey () : void {
$this->expectException(InvalidArgumentException::class);
$this->vector["foo"];
}
public function testOffsetExists () : void {
$this->assertTrue(isset($this->vector[0]));
$this->assertFalse(isset($this->vector[8]));
}
public function testOffsetSetWithoutOffset () : void {
$this->vector[] = 6;
$this->assertEquals(6, $this->vector[5]);
}
public function testOffsetSet () : void {
$this->vector[0] = 9;
$this->assertEquals(9, $this->vector[0]);
}
public function testOffsetUnset () : void {
unset($this->vector[2]);
$expected = [
0 => 1,
1 => 2,
// vector[2] has been unset
3 => 4,
4 => 5,
];
$this->assertEquals($expected, $this->vector->toArray());
}
///
/// IteratorAggregate
///
public function testGetIterator () : void {
$this->assertEquals([1, 2, 3, 4, 5], iterator_to_array($this->vector));
}
///
/// WithCollection trait
///
public function testFirst () : void {
$this->assertEquals(1, $this->vector->first());
}
public function testFirstWhenEmpty () : void {
$vector = new Vector;
$this->expectException(OutOfRangeException::class);
$vector->first();
}
public function testFirstOr () : void {
$this->assertEquals(1, $this->vector->firstOr(2));
}
public function testFirstOrWhenEmpty () : void {
$vector = new Vector;
$this->assertEquals(2, $vector->firstOr(2));
}
}
File Metadata
Details
Attached
Mime Type
text/x-diff
Expires
Mon, Nov 25, 03:33 (22 h, 42 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
2258349
Default Alt Text
(31 KB)
Attached To
Mode
rKERUALD Keruald libraries development repository
Attached
Detach File
Event Timeline
Log In to Comment