linq_tests.php
<?php
require_once('linq.php');
use \Linq\QueryEnumerable as QE;
echo "\nMinimal creation/iteration\n";
(function(){
$qe = new QE([3,1,4,1,5]);
$target = '3 1 4 1 5 ';
$result = '';
foreach($qe->Enumerate() as $q)
{
$result .= $q . ' ';
}
echo "$result\n$target\n", ($result === $target ? 'PASS' : "FAIL\x07"), "\n\n";
})();
echo "\nAggregate\n";
(function(){
$words = explode(' ', "the quick brown fox jumps over the lazy dog");
$target = '[dog lazy the over jumps fox brown quick the ]';
$reversed = (new QE($words))
->Aggregate(
fn($workingSentence, $next) => "$next $workingSentence"
);
$result = "[$reversed]";
echo "$result\n$target\n", ($result === $target ? 'PASS' : "FAIL\x07"), "\n\n";
})();
(function(){
$ints = [4, 8, 8, 3, 9, 0, 7, 8, 2];
$target = '';
$target = 'The number of even integers is: 6';
$numEven = (new QE($ints))->Aggregate(
fn($total, $next) => $total + 1 - ($next % 2),
0
);
$result = "The number of even integers is: $numEven";
echo "$result\n$target\n", ($result === $target ? 'PASS' : "FAIL\x07"), "\n\n";
})();
(function(){
$fruits = ["apple", "mango", "orange", "passionfruit", "grape"];
$target = 'The fruit with the longest name is PASSIONFRUIT';
$longestName = (new QE($fruits))
->Aggregate(fn($longest, $next) => strlen($next) > strlen($longest) ? $next : $longest,
'banana',
fn($fruit) => strtoupper($fruit));
$result = "The fruit with the longest name is $longestName";
echo "$result\n$target\n", ($result === $target ? 'PASS' : "FAIL\x07"), "\n\n";
})();
echo "\nAll\n";
(function(){
$pets = [
(object)['Name' => 'Barley', 'Age' => 10],
(object)['Name' => 'Boots', 'Age' => 4],
(object)['Name' => 'Whiskers', 'Age' => 6],
];
$target = "Not all pet names start with 'B'.";
$allStartWithB = (new QE($pets))
->All(fn($pet) => substr($pet->Name, 0, 1) == 'B');
$result = ($allStartWithB ? 'All' : 'Not all') . " pet names start with 'B'.";
echo "$result\n$target\n", ($result === $target ? 'PASS' : "FAIL\x07"), "\n\n";
})();
(function(){
$people = [
(object)['LastName' => "Haas",
'Pets' => [
(object)['Name' => "Barley", 'Age' => 10],
(object)['Name' => "Boots", 'Age' => 14],
(object)['Name' => "Whiskers", 'Age' => 6]]],
(object)['LastName' => "Fakhouri",
'Pets' => [
(object)['Name' => "Snowball", 'Age' => 1]]],
(object)['LastName' => "Antebi",
'Pets' => [
(object)['Name' => "Belle", 'Age' => 8]]],
(object)['LastName' => "Philips",
'Pets' => [
(object)['Name' => "Sweetie", 'Age' => 2],
(object)['Name' => "Rover", 'Age' => 13]]]];
$target = 'Haas Antebi';
$names = (new QE($people))
->Where(fn($person) => (new QE($person->Pets))->All(fn($pet) => $pet->Age > 5))
->Select(fn($person) => $person->LastName)->ToArray();
$result = join(' ', $names);
echo "$result\n$target\n", ($result === $target ? 'PASS' : "FAIL\x07"), "\n\n";
})();
echo "\nAny\n";
(function(){
$numbers = [1, 2];
$target = "The list is not empty";
$hasElements = (new QE($numbers))->Any();
$result = sprintf("The list %s empty", $hasElements ? "is not" : "is");
echo "$result\n$target\n", ($result === $target ? 'PASS' : "FAIL\x07"), "\n\n";
})();
(function(){
$people = [
(object)['LastName' => "Haas",
'Pets' => [
(object)['Name' => "Barley", 'Age' => 10],
(object)['Name' => "Boots", 'Age' => 14],
(object)['Name' => "Whiskers", 'Age' => 6]]],
(object)['LastName' => "Fakhouri",
'Pets' => [
(object)['Name' => "Snowball", 'Age' => 1]]],
(object)['LastName' => "Antebi",
'Pets' => []],
(object)['LastName' => "Philips",
'Pets' => [
(object)['Name' => "Sweetie", 'Age' => 2],
(object)['Name' => "Rover", 'Age' => 13]]]];
$target = 'Haas Fakhouri Philips';
$names = (new QE($people))
->Where(fn($person) => (new QE($person->Pets))->Any())
->Select(fn($person) => $person->LastName)->ToArray();
$result = join(' ', $names);
echo "$result\n$target\n", ($result === $target ? 'PASS' : "FAIL\x07"), "\n\n";
})();
(function(){
$pets = [
(object)['Name' => "Barley", 'Age' => 8, 'Vaccinated' => true],
(object)['Name' => "Boots", 'Age' => 4, 'Vaccinated' => false],
(object)['Name' => "Whiskers", 'Age' => 1, 'Vaccinated' => false],
];
$target = 'There are unvaccinated animals over age one.';
$unvaccinated = (new QE($pets))
->Any(fn($p) => $p->Age > 1 && !$p->Vaccinated);
$result = sprintf("There %s unvaccinated animals over age one.", $unvaccinated ? "are" : "are not any");
echo "$result\n$target\n", ($result === $target ? 'PASS' : "FAIL\x07"), "\n\n";
})();
echo "\nAverage\n";
(function(){
$numbers = [10007, null, 37, 399846234235];
$target = round((10007 + 37 + 399846234235) / 3, 3);
$average = (new QE($numbers))->Average();
$result = round($average, 3);
echo "$result\n$target\n", ($result === $target ? 'PASS' : "FAIL\x07"), "\n\n";
})();
(function(){
$fruits = ['apple', 'banana', 'mango', 'orange', 'passionfruit', 'grape'];
$target = 6.5;
$average = (new QE($fruits))->Average('strlen');
$result = $average;
echo "$result\n$target\n", ($result === $target ? 'PASS' : "FAIL\x07"), "\n\n";
})();
echo "\nContains\n";
(function(){
$fruits = ['apple', 'banana', 'mango', 'orange', 'passionfruit', 'grape'];
$mango = 'mango';
$target = "The array does contain '$mango'.";
$contains = (new QE($fruits))->Contains($mango);
$result = sprintf("The array %s contain '$mango'.", $contains ? "does" : "does not");
echo "$result\n$target\n", ($result === $target ? 'PASS' : "FAIL\x07"), "\n\n";
})();
(function(){
$fruits = ['apple', 'banana', 'mango', 'passionfruit', 'grape'];
$orange = 'orange';
$target = "Another fruit's name is the same length as '$orange'.";
$contains = (new QE($fruits))->Contains($orange, fn($a, $b) => strlen($a) == strlen($b));
$result = sprintf("Another fruit's name %s the same length as '$orange'.", $contains ? "is" : "is not");
echo "$result\n$target\n", ($result === $target ? 'PASS' : "FAIL\x07"), "\n\n";
})();
echo "\nCount\n";
(function(){
$fruits = ['apple', 'banana', 'mango', 'orange', 'passionfruit', 'grape'];
$target = "There are 6 items in the array.";
$numberOfFruits = (new QE($fruits))->Count();
$result = "There are $numberOfFruits items in the array.";
echo "$result\n$target\n", ($result === $target ? 'PASS' : "FAIL\x07"), "\n\n";
})();
(function(){
$pets = [
(object)['Name' => "Barley", 'Age' => 8, 'Vaccinated' => true],
(object)['Name' => "Boots", 'Age' => 4, 'Vaccinated' => false],
(object)['Name' => "Whiskers", 'Age' => 1, 'Vaccinated' => false],
];
$target = "There are 2 unvaccinated animals.";
$numberUnvaccinated = (new QE($pets))->Count(fn($pet) => !$pet->Vaccinated);
$result = "There are $numberUnvaccinated unvaccinated animals.";
echo "$result\n$target\n", ($result === $target ? 'PASS' : "FAIL\x07"), "\n\n";
})();
echo "\nElementAt\n";
(function(){
$names = [
'Hartono, Tommy',
'Adams, Terry',
'Andersen, Henriette Thaulow',
'Hedlund, Magnus',
'Ito, Shu'];
$pickOne = 3; // Hedlund, Magnus
$target = "Hedlund, Magnus";
$result = (new QE($names))->ElementAt($pickOne);
echo "$result\n$target\n", ($result === $target ? 'PASS' : "FAIL\x07"), "\n\n";
})();
(function(){
$names = [
'Hartono, Tommy',
'Adams, Terry',
'Andersen, Henriette Thaulow',
'Hedlund, Magnus',
'Ito, Shu'];
$pickOne = 9; // OutOfBounds
echo "Invalid Access\n";
try
{
$result = (new QE($names))->ElementAt($pickOne);
echo "FAIL\x07\n\n";
}
catch(\OutOfBoundsException $e)
{
echo "PASS\n\n";
}
})();
echo "\nElementAtOrNull\n";
(function(){
$names = [
'Hartono, Tommy',
'Adams, Terry',
'Andersen, Henriette Thaulow',
'Hedlund, Magnus',
'Ito, Shu'];
$pickOne = 3; // Hedlund, Magnus
$target = "Hedlund, Magnus";
$result = (new QE($names))->ElementAtOrNull($pickOne);
echo "$result\n$target\n", ($result === $target ? 'PASS' : "FAIL\x07"), "\n\n";
})();
(function(){
$names = [
'Hartono, Tommy',
'Adams, Terry',
'Andersen, Henriette Thaulow',
'Hedlund, Magnus',
'Ito, Shu'];
$pickOne = 9;
$target = null;
echo "Invalid Access\n";
$result = (new QE($names))->ElementAtOrNull($pickOne);
echo ($result === $target ? 'PASS' : "FAIL\x07"), "\n\n";
})();
echo "\nFirst\n";
(function(){
$numbers = [9, 34, 65, 92, 87, 435, 3, 54, 83, 23, 87, 435, 67, 12, 19];
$target = 9;
$result = (new QE($numbers))->First();
echo "$result\n$target\n", ($result === $target ? 'PASS' : "FAIL\x07"), "\n\n";
})();
(function(){
$numbers = [9, 34, 65, 92, 87, 435, 3, 54, 83, 23, 87, 435, 67, 12, 19];
$target = 92;
$result = (new QE($numbers))->First(fn($n) => $n > 80);
echo "$result\n$target\n", ($result === $target ? 'PASS' : "FAIL\x07"), "\n\n";
})();
(function(){
$numbers = [9, 34, 65, 92, 87, 435, 3, 54, 83, 23, 87, 435, 67, 12, 19];
echo "Invalid Access\n";
try
{
$result = (new QE($numbers))->First(fn($n) => $n > 800);
echo "FAIL\x07\n\n";
}
catch(\UnderflowException $e)
{
echo "PASS\n\n";
}
})();
echo "\nFirstOrNull\n";
(function(){
$numbers = [9, 34, 65, 92, 87, 435, 3, 54, 83, 23, 87, 435, 67, 12, 19];
$target = 9;
$result = (new QE($numbers))->FirstOrNull();
echo "$result\n$target\n", ($result === $target ? 'PASS' : "FAIL\x07"), "\n\n";
})();
(function(){
$numbers = [];
$target = null;
$result = (new QE($numbers))->FirstOrNull();
echo "Invalid Access\n", ($result === $target ? 'PASS' : "FAIL\x07"), "\n\n";
})();
(function(){
$numbers = [9, 34, 65, 92, 87, 435, 3, 54, 83, 23, 87, 435, 67, 12, 19];
$target = null;
$result = (new QE($numbers))->FirstOrNull(fn($n) => $n > 800);
echo "Invalid Access\n", ($result === $target ? 'PASS' : "FAIL\x07"), "\n\n";
})();
echo "\nLast\n";
(function(){
$numbers = [9, 34, 65, 92, 87, 435, 3, 54, 83, 23, 87, 435, 67, 12, 19];
$target = 19;
$result = (new QE($numbers))->Last();
echo "$result\n$target\n", ($result === $target ? 'PASS' : "FAIL\x07"), "\n\n";
})();
(function(){
$numbers = [9, 34, 65, 92, 87, 435, 3, 54, 83, 23, 87, 435, 67, 12, 19];
$target = 435;
$result = (new QE($numbers))->Last(fn($n) => $n > 80);
echo "$result\n$target\n", ($result === $target ? 'PASS' : "FAIL\x07"), "\n\n";
})();
echo "\nLastOrNull\n";
(function(){
$numbers = [9, 34, 65, 92, 87, 435, 3, 54, 83, 23, 87, 435, 67, 12, 19];
$target = 19;
$result = (new QE($numbers))->LastOrNull();
echo "$result\n$target\n", ($result === $target ? 'PASS' : "FAIL\x07"), "\n\n";
})();
(function(){
$numbers = [];
$target = null;
$result = (new QE($numbers))->LastOrNull(fn($n) => $n > 800);
echo "Invalid Access\n", ($result === $target ? 'PASS' : "FAIL\x07"), "\n\n";
})();
(function(){
$numbers = [9, 34, 65, 92, 87, 435, 3, 54, 83, 23, 87, 435, 67, 12, 19];
$target = null;
$result = (new QE($numbers))->LastOrNull(fn($n) => $n > 800);
echo "Invalid Access\n", ($result === $target ? 'PASS' : "FAIL\x07"), "\n\n";
})();
echo "\nMax\n";
(function(){
$numbers = [4_294_967_296, 466_855_135, 81_125];
$target = "The largest number is 4294967296.";
$max = (new QE($numbers))->Max();
$result = "The largest number is $max.";
echo "$result\n$target\n", ($result === $target ? 'PASS' : "FAIL\x07"), "\n\n";
})();
(function(){
$pets = [
(object)['Name' => "Barley", 'Age' => 8],
(object)['Name' => "Boots", 'Age' => 4],
(object)['Name' => "Whiskers", 'Age' => 1],
];
$target = "The maximum pet age plus name length is 14."; // Barley
$max = (new QE($pets))->Max(fn($pet) => $pet->Age + strlen($pet->Name));
$result = "The maximum pet age plus name length is $max.";
echo "$result\n$target\n", ($result === $target ? 'PASS' : "FAIL\x07"), "\n\n";
})();
echo "\nMin\n";
(function(){
$numbers = [4_294_967_296, 466_855_135, 81_125];
$target = "The smallest number is 81125.";
$min = (new QE($numbers))->Min();
$result = "The smallest number is $min.";
echo "$result\n$target\n", ($result === $target ? 'PASS' : "FAIL\x07"), "\n\n";
})();
(function(){
$pets = [
(object)['Name' => "Barley", 'Age' => 8],
(object)['Name' => "Boots", 'Age' => 4],
(object)['Name' => "Whiskers", 'Age' => 1],
];
$target = "The youngest animal is age 1.";
$min = (new QE($pets))->Min(fn($pet) => $pet->Age);
$result = "The youngest animal is age $min.";
echo "$result\n$target\n", ($result === $target ? 'PASS' : "FAIL\x07"), "\n\n";
})();
echo "\nSequenceEqual\n";
(function(){
$pet1 = (object)['Name' => "Turbo", 'Age' => 2];
$pet2 = (object)['Name' => "Peanut", 'Age' => 8];
$pets1 = new QE([$pet1, $pet2]);
$pets2 = new QE([$pet1, $pet2]);
$target = "The lists are equal.";
$equal = $pets1->SequenceEqual($pets2);
$result = sprintf("The lists %s equal.", $equal ? "are" : "are NOT");
echo "$result\n$target\n", ($result === $target ? 'PASS' : "FAIL\x07"), "\n\n";
})();
(function(){
$pet1 = (object)['Name' => "Turbo", 'Age' => 2];
$pet2 = (object)['Name' => "Peanut", 'Age' => 8];
$pets1 = new QE([$pet1, $pet2]);
$pets2 = new QE([(object)['Name' => "Turbo", 'Age' => 2], (object)['Name' => "Peanut", 'Age' => 8]]);
$target = "The lists are NOT equal.";
$equal = $pets1->SequenceEqual($pets2);
$result = sprintf("The lists %s equal.", $equal ? "are" : "are NOT");
echo "$result\n$target\n", ($result === $target ? 'PASS' : "FAIL\x07"), "\n\n";
})();
(function(){
$pet1 = (object)['Name' => "Turbo", 'Age' => 2];
$pet2 = (object)['Name' => "Peanut", 'Age' => 8];
$pets1 = new QE([$pet1, $pet2]);
$pets2 = new QE([(object)['Name' => "Turbo", 'Age' => 2], (object)['Name' => "Peanut", 'Age' => 8]]);
$target = "The lists are equal.";
$equal = $pets1->SequenceEqual($pets2, fn($p1, $p2) => $p1->Name == $p2->Name && $p1->Age == $p2->Age);
$result = sprintf("The lists %s equal.", $equal ? "are" : "are NOT");
echo "$result\n$target\n", ($result === $target ? 'PASS' : "FAIL\x07"), "\n\n";
})();
echo "\nSingle\n";
(function(){
$fruits1 = ['orange'];
$target = "First query: orange";
$fruit1 = (new QE($fruits1))->Single();
$result = "First query: $fruit1";
echo "$result\n$target\n", ($result === $target ? 'PASS' : "FAIL\x07"), "\n\n";
})();
(function(){
$fruits2 = ['orange', 'apple'];
echo "Invalid Access\n";
try
{
$fruit2 = (new QE($fruits2))->Single();
echo "Second query: $fruit2\nFAIL\x07\n\n";
}
catch(\OverflowException $e)
{
echo "PASS\n\n";
}
})();
(function(){
$fruits0 = [];
echo "Invalid Access\n";
try
{
$fruit0 = (new QE($fruits0))->Single();
echo "Third query: $fruit0\nFAIL\x07\n\n";
}
catch(\UnderflowException $e)
{
echo "PASS\n\n";
}
})();
(function(){
$fruits = ['apple', 'banana', 'mango', 'orange', 'passionfruit', 'grape'];
$target = "First query: passionfruit";
$fruit = (new QE($fruits))->Single(fn($fruit) => strlen($fruit) > 10); // Passionfruit
$result = "First query: $fruit";
echo "$result\n$target\n", ($result === $target ? 'PASS' : "FAIL\x07"), "\n\n";
})();
(function(){
$fruits = ['apple', 'banana', 'mango', 'orange', 'passionfruit', 'grape'];
echo "Invalid Access\n";
try
{
$fruit = (new QE($fruits))->Single(fn($fruit) => strlen($fruit) == 5);
echo "Second query: $fruit\nFAIL\x07\n\n";
}
catch(\OverflowException $e)
{
echo "PASS\n\n";
}
})();
(function(){
$fruits = ['apple', 'banana', 'mango', 'orange', 'passionfruit', 'grape'];
echo "Invalid Access\n";
try
{
$fruit = (new QE($fruits))->Single(fn($fruit) => strlen($fruit) > 15);
echo "Third query: $fruit\nFAIL\x07\n\n";
}
catch(\UnderflowException $e)
{
echo "PASS\n\n";
}
})();
echo "\nSingleOrNull\n";
(function(){
$fruits1 = ['orange'];
$target = "First query: orange";
$fruit1 = (new QE($fruits1))->SingleOrNull();
$result = "First query: $fruit1";
echo "$result\n$target\n", ($result === $target ? 'PASS' : "FAIL\x07"), "\n\n";
})();
(function(){
$fruits2 = ['orange', 'apple'];
$target = null;
echo "Invalid Access\n";
try
{
$fruit2 = (new QE($fruits2))->SingleOrNull();
echo "Second query: $fruit2\nFAIL\x07\n\n";
}
catch(\OverflowException $e)
{
echo "PASS\n\n";
}
})();
(function(){
$fruits0 = [];
$target = null;
$result = (new QE($fruits0))->SingleOrNull();
echo "$result\n$target\n", ($result === $target ? 'PASS' : "FAIL\x07"), "\n\n";
})();
(function(){
$fruits = ['apple', 'banana', 'mango', 'orange', 'passionfruit', 'grape'];
$target = "First query: passionfruit";
$fruit = (new QE($fruits))->SingleOrNull(fn($fruit) => strlen($fruit) > 10); // Passionfruit
$result = "First query: $fruit";
echo "$result\n$target\n", ($result === $target ? 'PASS' : "FAIL\x07"), "\n\n";
})();
(function(){
$fruits = ['apple', 'banana', 'mango', 'orange', 'passionfruit', 'grape'];
echo "Invalid Access\n";
try
{
$fruit = (new QE($fruits))->SingleOrNull(fn($fruit) => strlen($fruit) == 5);
echo "Second query: $fruit\nFAIL\x07\n\n";
}
catch(\OverflowException $e)
{
echo "PASS\n\n";
}
})();
(function(){
$fruits = ['apple', 'banana', 'mango', 'orange', 'passionfruit', 'grape'];
$target = null;
$result = (new QE($fruits))->SingleOrNull(fn($fruit) => strlen($fruit) > 15);
echo "$result\n$target\n", ($result === $target ? 'PASS' : "FAIL\x07"), "\n\n";
})();
echo "\nSum\n";
(function(){
$numbers = [43.68, 1.25, 583.7, 6.5];
$target = round(array_sum($numbers), 2);
$target = "The sum of the numbers is $target.";
$sum = (new QE($numbers))->Sum();
$result = round($sum, 2);
$result = "The sum of the numbers is $result.";
echo "$result\n$target\n", ($result === $target ? 'PASS' : "FAIL\x07"), "\n\n";
})();
(function(){
$packages = [
(object)['Company' => 'Coho Vineyard', 'Weight' => 252],
(object)['Company' => 'Lucerne Publishing', 'Weight' => 187],
(object)['Company' => 'Wingtip Toys', 'Weight' => 60],
(object)['Company' => 'Adventure Works', 'Weight' => 338],
];
$target = "The total weight of the packages is 837.";
$totalWeight = (new QE($packages))->Sum(fn($pkg) => $pkg->Weight);
$result = "The total weight of the packages is $totalWeight.";
echo "$result\n$target\n", ($result === $target ? 'PASS' : "FAIL\x07"), "\n\n";
})();
echo "\nToArray\n";
(function(){
$target = ['foo', 17, false];
$result = (new QE($target))->ToArray();
echo ($result === $target ? 'PASS' : "FAIL\x07"), "\n\n";
})();
echo "\nEmpty\n";
(function(){
$target = [];
$result = QE::Empty()->ToArray();
echo ($result === $target ? 'PASS' : "FAIL\x07"), "\n\n";
})();
(function(){
$target = [];
try
{
$result = QE::Empty()->Single();
echo "FAIL\x07\n\n";
}
catch(\UnderflowException $e)
{
echo "PASS\n\n";
}
})();
echo "\nRepeat\n";
(function(){
$target = [17,17,17,17];
$result = QE::Repeat(17, 4)->ToArray();
echo ($result === $target ? 'PASS' : "FAIL\x07"), "\n\n";
})();
(function(){
$target = [];
try
{
$result = QE::Repeat('fnord', 0)->ToArray();
echo "FAIL\x07\n\n";
}
catch(\OutOfRangeException $e)
{
echo "PASS\n\n";
}
})();
echo "\nRange\n";
(function(){
$target = [8,9,10,11];
$result = QE::Range(8, 4)->ToArray();
echo ($result === $target ? 'PASS' : "FAIL\x07"), "\n\n";
})();
(function(){
try
{
$result = QE::Range(PHP_INT_MAX - 8, 97)->ToArray();
echo "FAIL\x07\n\n";
}
catch(\OutOfRangeException $e)
{
echo "PASS\n\n";
}
})();
(function(){
try
{
$result = QE::Range(97, -8)->ToArray();
echo "FAIL\x07\n\n";
}
catch(\OutOfRangeException $e)
{
echo "PASS\n\n";
}
})();
echo "\nAppend\n";
(function(){
$numbers = [8,9,10,11];
$old_number_qe = (new QE($numbers));
$new_number_qe = $old_number_qe->Append(5);
$before_target = "8, 9, 10, 11";
$after_target = "8, 9, 10, 11, 5";
$before_result = join(', ', $old_number_qe->ToArray());
$after_result = join(', ', $new_number_qe->ToArray());
echo ($before_result === $before_target && $after_target == $after_result ? 'PASS' : "FAIL\x07"), "\n\n";
})();
echo "\nConcat\n";
(function(){
$getCats = function()
{
return (new QE([
(object)['Name' => "Barley", 'Age' => 8],
(object)['Name' => "Boots", 'Age' => 4],
(object)['Name' => "Whiskers", 'Age' => 1],
]));
};
$getDogs = function()
{
return (new QE([
(object)['Name' => "Bounder", 'Age' => 3],
(object)['Name' => "Snoopy", 'Age' => 14],
(object)['Name' => "Fido", 'Age' => 9],
]));
};
$target = "Barley Boots Whiskers Bounder Snoopy Fido";
$cats = $getCats();
$dogs = $getDogs();
$query = $cats->Select(fn($cat) => $cat->Name)->Concat($dogs->Select(fn($dog) => $dog->Name));
$result = join(' ', $query->ToArray());
echo "$result\n$target\n", ($result === $target ? 'PASS' : "FAIL\x07"), "\n\n";
})();
(function(){
$getCats = function()
{
return (new QE([
(object)['Name' => "Barley", 'Age' => 8],
(object)['Name' => "Boots", 'Age' => 4],
(object)['Name' => "Whiskers", 'Age' => 1],
]));
};
$getDogs = function()
{
return (new QE([
(object)['Name' => "Bounder", 'Age' => 3],
(object)['Name' => "Snoopy", 'Age' => 14],
(object)['Name' => "Fido", 'Age' => 9],
]));
};
$target = "Barley Boots Whiskers Bounder Snoopy Fido";
$cats = $getCats();
$dogs = $getDogs();
$query = (new QE([
$cats->Select(fn($cat) => $cat->Name),
$dogs->Select(fn($dog) => $dog->Name)]))->SelectMany(fn($name) => $name);
$result = join(' ', $query->ToArray());
echo "$result\n$target\n", ($result === $target ? 'PASS' : "FAIL\x07"), "\n\n";
})();
echo "\nUnion\n";
(function(){
$ints1 = [5,3,9,7,5,9,3,7];
$ints2 = [8,3,6,4,4,9,1,0];
$target = "539786410";
$union = (new QE($ints1))->Union(new QE($ints2));
$result = join($union->ToArray());
echo "$result\n$target\n", ($result === $target ? 'PASS' : "FAIL\x07"), "\n\n";
})();
(function(){
$equal = function($left, $right)
{
if($left === $right)
{
return true;
}
if($left === null || $right === null)
{
return false;
}
else
{
return $left->Name == $right->Name && $left->Code == $right->Code;
}
};
$store1 = [
(object)['Name' => 'apple', 'Code' => 9],
(object)['Name' => 'orange', 'Code' => 4],
];
$store2 = [
(object)['Name' => 'apple', 'Code' => 9],
(object)['Name' => 'lemon', 'Code' => 12],
];
$target = "apple 9, orange 4, lemon 12";
$union = (new QE($store1))->Union(new QE($store2), $equal);
$result = [];
foreach($union->Enumerate() as $fruit)
{
$result[] = "{$fruit->Name} {$fruit->Code}";
}
$result = join(", ", $result);
echo "$result\n$target\n", ($result === $target ? 'PASS' : "FAIL\x07"), "\n\n";
})();
echo "\nDefaultIfEmpty\n";
(function(){
$defaultPet = (object)['Name' => "Default Pet", 'Age' => 0];
$pets = [
(object)['Name' => "Barley", 'Age' => 8],
(object)['Name' => "Boots", 'Age' => 4],
(object)['Name' => "Whiskers", 'Age' => 1],
];
$target = "Barley, Boots, Whiskers";
$list = (new QE($pets))->DefaultIfEmpty($defaultPet);
$result = join(', ', $list->Select(fn($pet) => $pet->Name)->ToArray());
echo "$result\n$target\n", ($result === $target ? 'PASS' : "FAIL\x07"), "\n\n";
})();
(function(){
$defaultPet = (object)['Name' => "Default Pet", 'Age' => 0];
$pets = [
];
$target = "Default Pet";
$list = (new QE($pets))->DefaultIfEmpty($defaultPet);
$result = join(', ', $list->Select(fn($pet) => $pet->Name)->ToArray());
echo "$result\n$target\n", ($result === $target ? 'PASS' : "FAIL\x07"), "\n\n";
})();
echo "\nDistinct\n";
(function(){
$ages = [21, 46, 46, 55, 17, 55, 55];
$target = "21 46 55 17";
$distinctAges = (new QE($ages))->Distinct();
$result = join(' ', $distinctAges->ToArray());
echo "$result\n$target\n", ($result === $target ? 'PASS' : "FAIL\x07"), "\n\n";
})();
(function(){
$equal = function($left, $right)
{
if($left === $right)
{
return true;
}
if($left === null || $right === null)
{
return false;
}
else
{
return $left->Name == $right->Name && $left->Code == $right->Code;
}
};
$products = [
(object)['Name' => 'apple', 'Code' => 9],
(object)['Name' => 'orange', 'Code' => 4],
(object)['Name' => 'apple', 'Code' => 9],
(object)['Name' => 'lemon', 'Code' => 12],
];
$target = "apple 9, orange 4, lemon 12";
$noDuplicates = (new QE($products))->Distinct($equal);
$result = join(', ', $noDuplicates->Select(fn($fruit) => "{$fruit->Name} {$fruit->Code}")->ToArray());
echo "$result\n$target\n", ($result === $target ? 'PASS' : "FAIL\x07"), "\n\n";
})();
echo "\nExcept\n";
(function(){
$numbers1 = [20, 20, 21, 22, 23, 23, 24, 25];
$numbers2 = [22];
$target = "20, 21, 23, 24, 25";
$onlyInFirst = (new QE($numbers1))->Except(new QE($numbers2));
$result = join(', ', $onlyInFirst->ToArray());
echo "$result\n$target\n", ($result === $target ? 'PASS' : "FAIL\x07"), "\n\n";
})();
(function(){
$equal = function($left, $right)
{
if($left === $right)
{
return true;
}
if($left === null || $right === null)
{
return false;
}
else
{
return $left->Name == $right->Name && $left->Code == $right->Code;
}
};
$products = [
(object)['Name' => 'apple', 'Code' => 9],
(object)['Name' => 'orange', 'Code' => 4],
(object)['Name' => 'apple', 'Code' => 9],
(object)['Name' => 'lemon', 'Code' => 12],
];
$removed = [(object)['Name' => 'apple', 'Code' => 9]];
$target = "orange 4, lemon 12";
$except = (new QE($products))->Except(new QE($removed), $equal);
$result = join(', ', $except->Select(fn($fruit) => "{$fruit->Name} {$fruit->Code}")->ToArray());
echo "$result\n$target\n", ($result === $target ? 'PASS' : "FAIL\x07"), "\n\n";
})();
echo "\nGroupBy\n";
(function(){
$pets = [
(object)['Name' => "Barley", 'Age' => 8],
(object)['Name' => "Boots", 'Age' => 4],
(object)['Name' => "Whiskers", 'Age' => 1],
(object)['Name' => "Daisy", 'Age' => 4],
];
$target = "8\n\tBarley\n4\n\tBoots\n\tDaisy\n1\n\tWhiskers\n";
$query = (new QE($pets))->GroupBy(fn($pet) => $pet->Age, fn($pet) => $pet->Name);
$result = '';
foreach($query->Enumerate() as $key => $petGroup)
{
$result .= "$key\n";
foreach($petGroup->Enumerate() as $name)
{
$result .= "\t$name\n";
}
}
echo "$result\n$target\n", ($result === $target ? 'PASS' : "FAIL\x07"), "\n\n";
})();
(function(){
$pets = [
(object)['Name' => "Barley", 'Age' => 8.3],
(object)['Name' => "Boots", 'Age' => 4.9],
(object)['Name' => "Whiskers", 'Age' => 1.5],
(object)['Name' => "Daisy", 'Age' => 4.3],
];
$target = "\nAge Group: 8
Number of pets in this age group: 1
Minimum age: " . 8.3 . "
Maximum age: " . 8.3 . "
Age Group: 4
Number of pets in this age group: 2
Minimum age: " . min(4.9, 4.3) . "
Maximum age: " . max(4.9, 4.3) . "
Age Group: 1
Number of pets in this age group: 1
Minimum age: " . 1.5 . "
Maximum age: " . 1.5 . "\n";
$query = (new QE($pets))->GroupBy(
fn($pet) => floor($pet->Age),
null,
fn($age, $pets) => (object)[
'Key' => $age,
'Count' => $pets->Count(),
'Min' => $pets->Min(fn($pet) => $pet->Age),
'Max' => $pets->Max(fn($pet) => $pet->Age)]
);
$result = '';
foreach($query->Enumerate() as $key => $petGroup)
{
$result .= "\nAge Group: $key\n";
$result .= "Number of pets in this age group: {$petGroup->Count}\n";
$result .= "Minimum age: {$petGroup->Min}\n";
$result .= "Maximum age: {$petGroup->Max}\n";
}
echo "$result\n$target\n", ($result === $target ? 'PASS' : "FAIL\x07"), "\n\n";
})();
echo "\nGroupJoin\n";
(function(){
$people = [
$magnus = (object)['Name' => "Hedlund, Magnus"],
$terry = (object)['Name' => "Adams, Terry"],
$charlotte = (object)['Name' => "Weiss, Charlotte"],
];
$pets = [
(object)['Name' => "Barley", 'Owner' => $terry],
(object)['Name' => "Boots", 'Owner' => $terry],
(object)['Name' => "Whiskers", 'Owner' => $charlotte],
(object)['Name' => "Daisy", 'Owner' => $magnus],
];
$target =
"Hedlund, Magnus: Daisy\n" .
"Adams, Terry: Barley, Boots\n" .
"Weiss, Charlotte: Whiskers\n";
$query = (new QE($people))->GroupJoin(new QE($pets),
fn($person) => $person,
fn($pet) => $pet->Owner,
fn($person, $petCollection) => (object)[
'OwnerName' => $person->Name,
'Pets' => $petCollection->Select(fn($pet) => $pet->Name)
]);
$result = '';
foreach($query->Enumerate() as $obj)
{
$result .= $obj->OwnerName . ": " . join(', ', $obj->Pets->ToArray()) . "\n";
}
echo "$result\n$target\n", ($result === $target ? 'PASS' : "FAIL\x07"), "\n\n";
})();
echo "\nIntersect\n";
(function(){
$id1 = [44, 26, 92, 30, 71, 38];
$id2 = [39, 59, 83, 47, 26, 4, 30];
$target = "26 30";
$query = (new QE($id1))->Intersect(new QE($id2));
$result = join(" ", $query->ToArray());
echo "$result\n$target\n", ($result === $target ? 'PASS' : "FAIL\x07"), "\n\n";
})();
(function(){
$store1 = [
(object)['Name' => "apple", 'Code' => 9],
(object)['Name' => "orange", 'Code' => 4],
];
$store2 = [
(object)['Name' => "apple", 'Code' => 9],
(object)['Name' => "lemon", 'Code' => 12],
];
$target = "apple 9";
$query = (new QE($store1))->Intersect(new QE($store2), function($a, $b)
{
if($a === null || $b === null)
{
return $a === null && $b === null;
}
else
{
return $a->Name == $b->Name && $a->Code == $b->Code;
}
});
$result = join(", ", $query->Select(fn($fruit) => "{$fruit->Name} {$fruit->Code}")->ToArray());
echo "$result\n$target\n", ($result === $target ? 'PASS' : "FAIL\x07"), "\n\n";
})();
echo "\nJoin\n";
(function(){
$people = [
$magnus = (object)['Name' => "Hedlund, Magnus"],
$terry = (object)['Name' => "Adams, Terry"],
$charlotte = (object)['Name' => "Weiss, Charlotte"],
];
$pets = [
(object)['Name' => "Barley", 'Owner' => $terry],
(object)['Name' => "Boots", 'Owner' => $terry],
(object)['Name' => "Whiskers", 'Owner' => $charlotte],
(object)['Name' => "Daisy", 'Owner' => $magnus],
];
$target = "Hedlund, Magnus - Daisy\n" .
"Adams, Terry - Barley\n" .
"Adams, Terry - Boots\n" .
"Weiss, Charlotte - Whiskers\n";
$query = (new QE($people))->Join(new QE($pets),
fn($person) => $person,
fn($pet) => $pet->Owner,
fn($person, $pet) => (object)['OwnerName' => $person->Name, 'Pet' => $pet->Name],
);
$result = '';
foreach($query->Enumerate() as $obj)
{
$result .= "{$obj->OwnerName} - {$obj->Pet}\n";
}
echo "$result\n$target\n", ($result === $target ? 'PASS' : "FAIL\x07"), "\n\n";
})();
echo "\nOrderBy\n";
(function(){
$pets = [
(object)['Name' => 'Barley', 'Age' => 8],
(object)['Name' => 'Boots', 'Age' => 4],
(object)['Name' => 'Whiskers', 'Age' => 1],
(object)['Name' => 'Mog', 'Age' => 4],
];
$target = "Whiskers - 1, Boots - 4, Mog - 4, Barley - 8";
$query = (new QE($pets))->OrderBy(fn($pet) => $pet->Age);
$result = join(', ', $query->Select(fn($pet) => "{$pet->Name} - {$pet->Age}")->ToArray());
echo "$result\n$target\n", ($result === $target ? 'PASS' : "FAIL\x07"), "\n\n";
})();
(function(){
$pets = [
(object)['Name' => 'Barley', 'Age' => 8],
(object)['Name' => 'Boots', 'Age' => 4],
(object)['Name' => 'Whiskers', 'Age' => 1],
(object)['Name' => 'Mog', 'Age' => 4],
];
$target = "Mog - 4, Boots - 4, Barley - 8, Whiskers - 1";
$query = (new QE($pets))->OrderBy(fn($pet) => $pet->Name, fn($a, $b) => strlen($a) - strlen($b));
$result = join(', ', $query->Select(fn($pet) => "{$pet->Name} - {$pet->Age}")->ToArray());
echo "$result\n$target\n", ($result === $target ? 'PASS' : "FAIL\x07"), "\n\n";
})();
echo "\nOrderByDescending\n";
(function(){
$pets = [
(object)['Name' => 'Barley', 'Age' => 8],
(object)['Name' => 'Boots', 'Age' => 4],
(object)['Name' => 'Whiskers', 'Age' => 1],
(object)['Name' => 'Mog', 'Age' => 4],
];
$target = "Barley - 8, Boots - 4, Mog - 4, Whiskers - 1";
$query = (new QE($pets))->OrderByDescending(fn($pet) => $pet->Age);
$result = join(', ', $query->Select(fn($pet) => "{$pet->Name} - {$pet->Age}")->ToArray());
echo "$result\n$target\n", ($result === $target ? 'PASS' : "FAIL\x07"), "\n\n";
})();
(function(){
$pets = [
(object)['Name' => 'Barley', 'Age' => 8],
(object)['Name' => 'Boots', 'Age' => 4],
(object)['Name' => 'Whiskers', 'Age' => 1],
(object)['Name' => 'Mog', 'Age' => 4],
];
$target = "Whiskers - 1, Barley - 8, Boots - 4, Mog - 4";
$query = (new QE($pets))->OrderByDescending(fn($pet) => $pet->Name, fn($a, $b) => strlen($a) - strlen($b));
$result = join(', ', $query->Select(fn($pet) => "{$pet->Name} - {$pet->Age}")->ToArray());
echo "$result\n$target\n", ($result === $target ? 'PASS' : "FAIL\x07"), "\n\n";
})();
echo "\nSelect\n";
(function(){
$fruits = ['apple', 'banana', 'mango', 'orange', 'passionfruit', 'grape'];
$target = "5, 6, 5, 6, 12, 5";
$query = (new QE($fruits))->Select(fn($fruit) => strlen($fruit));
$result = join(', ', $query->ToArray());
echo "$result\n$target\n", ($result === $target ? 'PASS' : "FAIL\x07"), "\n\n";
})();
(function(){
$fruits = ['apple', 'banana', 'mango', 'orange', 'passionfruit', 'grape'];
$target = "[0 => ], [1 => b], [2 => ma], [3 => ora], [4 => pass], [5 => grape]";
$query = (new QE($fruits))->Select(fn($fruit, $idx) => [$idx, substr($fruit, 0, $idx)]);
$result = join(', ', $query->Select(fn($res) => "[{$res[0]} => {$res[1]}]")->ToArray());
echo "$result\n$target\n", ($result === $target ? 'PASS' : "FAIL\x07"), "\n\n";
})();
echo "\nSelectMany\n";
(function(){
$petOwners = [
(object)['Name' => "Higa, Sidney", 'Pets' => ['Scruffy', 'Sam']],
(object)['Name' => "Ashkenazi, Romen", 'Pets' => ['Walker', 'Sugar']],
(object)['Name' => "Price, Vernette", 'Pets' => ['Scratches', 'Diesel']],
(object)['Name' => "Hines, Patrick", 'Pets' => ['Dusty']],
];
$target = "0Scruffy, 0Sam, 1Walker, 1Sugar, 2Scratches, 2Diesel, 3Dusty";
$query = (new QE($petOwners))->SelectMany(
fn($petOwner, $index) => (new QE($petOwner->Pets))->Select(fn($pet) => "$index$pet"));
$result = join(', ', $query->ToArray());
echo "$result\n$target\n", ($result === $target ? 'PASS' : "FAIL\x07"), "\n\n";
})();
(function(){
$petOwners = [
(object)['Name' => "Higa", 'Pets' => ['Scruffy', 'Sam']],
(object)['Name' => "Ashkenazi", 'Pets' => ['Walker', 'Sugar']],
(object)['Name' => "Price", 'Pets' => ['Scratches', 'Diesel']],
(object)['Name' => "Hines", 'Pets' => ['Dusty']],
];
$target = "{Owner=Higa, Pet=Scruffy}\n"
. "{Owner=Higa, Pet=Sam}\n"
. "{Owner=Ashkenazi, Pet=Sugar}\n"
. "{Owner=Price, Pet=Scratches}\n";
$query = (new QE($petOwners))->SelectMany(
fn($petOwner) => $petOwner->Pets,
fn($petOwner, $petName) => ['PetOwner' => $petOwner, 'PetName' => $petName])
->Where(fn($ownerAndPet) => substr($ownerAndPet['PetName'], 0, 1) == 'S')
->Select(fn($ownerAndPet) => (object)['Owner' => $ownerAndPet['PetOwner']->Name, 'Pet' => $ownerAndPet['PetName']]);
$result = '';
foreach($query->Enumerate() as $ownerAndPet)
{
$result .= "{Owner={$ownerAndPet->Owner}, Pet={$ownerAndPet->Pet}}\n";
}
echo "$result\n$target\n", ($result === $target ? 'PASS' : "FAIL\x07"), "\n\n";
})();
echo "\nSkip\n";
(function(){
$grades = [59, 82, 70, 56, 92, 98, 85];
$target = "All grades except the top three are: 82, 70, 59, 56";
$query = (new QE($grades))->OrderByDescending(fn($x) => $x)->Skip(3);
$result = "All grades except the top three are: " . join(', ', $query->ToArray());
echo "$result\n$target\n", ($result === $target ? 'PASS' : "FAIL\x07"), "\n\n";
})();
echo "\nSkipWhile\n";
(function(){
$grades = [59, 82, 70, 56, 92, 98, 85];
$target = "All grades below 80: 70, 59, 56";
$query = (new QE($grades))->OrderByDescending(fn($x) => $x)->SkipWhile(fn($grade) => $grade >= 80);
$result = "All grades below 80: " . join(', ', $query->ToArray());
echo "$result\n$target\n", ($result === $target ? 'PASS' : "FAIL\x07"), "\n\n";
})();
echo "\nTake\n";
(function(){
$grades = [59, 82, 70, 56, 92, 98, 85];
$target = "The top three grades are: 98, 92, 85";
$query = (new QE($grades))->OrderByDescending(fn($x) => $x)->Take(3);
$result = "The top three grades are: " . join(', ', $query->ToArray());
echo "$result\n$target\n", ($result === $target ? 'PASS' : "FAIL\x07"), "\n\n";
})();
echo "\nTakeWhile\n";
(function(){
$fruits = ['apple', 'banana', 'mango', 'orange', 'passionfruit', 'grape'];
$target = "apple, banana, mango";
$query = (new QE($fruits))->TakeWhile(fn($fruit) => $fruit != "orange");
$result = join(', ', $query->ToArray());
echo "$result\n$target\n", ($result === $target ? 'PASS' : "FAIL\x07"), "\n\n";
})();
(function(){
$fruits = ['apple', 'passionfruit', 'banana', 'mango', 'orange', 'blueberry', 'grape', 'strawberry'];
$target = "apple, passionfruit, banana, mango, orange, blueberry";
$query = (new QE($fruits))->TakeWhile(fn($fruit, $index) => strlen($fruit) >= $index);
$result = join(', ', $query->ToArray());
echo "$result\n$target\n", ($result === $target ? 'PASS' : "FAIL\x07"), "\n\n";
})();
echo "\nThenBy\n";
(function(){
$fruits = ['grape', 'passionfruit', 'banana', 'mango', 'orange', 'raspberry', 'apple', 'blueberry'];
$target = "apple, grape, mango, banana, orange, blueberry, raspberry, passionfruit";
$query = (new QE($fruits))
->OrderBy(fn($fruit) => strlen($fruit))
->ThenBy(fn($fruit) => $fruit);
$result = join(', ', $query->ToArray());
echo "$result\n$target\n", ($result === $target ? 'PASS' : "FAIL\x07"), "\n\n";
})();
echo "\nThenByDescending\n";
(function(){
$fruits = ["apPLe", "baNanA", "apple", "APple", "orange", "BAnana", "ORANGE", "apPLE"];
$target = "apPLe, apple, APple, apPLE, orange, ORANGE, baNanA, BAnana";
$query = (new QE($fruits))
->OrderBy(fn($fruit) => strlen($fruit))
->ThenByDescending(fn($fruit) => $fruit, 'strcasecmp');
$result = join(', ', $query->ToArray());
echo "$result\n$target\n", ($result === $target ? 'PASS' : "FAIL\x07"), "\n\n";
})();
echo "\nWhere\n";
(function(){
$fruits = ['apple', 'passionfruit', 'banana', 'mango', 'orange', 'blueberry', 'grape', 'strawberry'];
$target = 'apple, mango, grape';
$query = (new QE($fruits))
->Where(fn($fruit) => strlen($fruit) < 6);
$result = join(', ', $query->ToArray());
echo "$result\n$target\n", ($result === $target ? 'PASS' : "FAIL\x07"), "\n\n";
})();
echo "\nZip\n";
(function(){
$numbers = [1, 2, 3, 4];
$words = ['one', 'two', 'three'];
$target = "1=one, 2=two, 3=three";
$query = (new QE($numbers))->Zip(new QE($words), fn($a, $b) => "$a=$b");
$result = join(', ', $query->ToArray());
echo "$result\n$target\n", ($result === $target ? 'PASS' : "FAIL\x07"), "\n\n";
})();