move query helpers to internal namespace
This commit is contained in:
parent
483375240b
commit
b836bc5e8f
@ -26,6 +26,7 @@
|
|||||||
"./src/Predicates/index.php",
|
"./src/Predicates/index.php",
|
||||||
"./src/Collections/Internal/functions.php",
|
"./src/Collections/Internal/functions.php",
|
||||||
"./src/Collections/Internal/containers.php",
|
"./src/Collections/Internal/containers.php",
|
||||||
|
"./src/Collections/Internal/queries.php",
|
||||||
"./src/Collections/transforms.php",
|
"./src/Collections/transforms.php",
|
||||||
"./src/Collections/collectors.php",
|
"./src/Collections/collectors.php",
|
||||||
"./src/Collections/queries.php"
|
"./src/Collections/queries.php"
|
||||||
|
|||||||
97
src/Collections/Internal/queries.php
Normal file
97
src/Collections/Internal/queries.php
Normal file
@ -0,0 +1,97 @@
|
|||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* Copyright 2026 Kacper Donat
|
||||||
|
*
|
||||||
|
* @author Kacper "Kadet" Donat <kacper@kadet.net>
|
||||||
|
*
|
||||||
|
* Full license available in separate LICENSE file
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace Kadet\Functional\Collections\Internal;
|
||||||
|
|
||||||
|
use Kadet\Functional\Exception\EmptyCollectionException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Yields [key, value] pairs of $data from the end, without copying it where the container allows.
|
||||||
|
*
|
||||||
|
* @internal
|
||||||
|
*
|
||||||
|
* @param iterable<mixed, mixed> $data
|
||||||
|
*
|
||||||
|
* @return \Generator<int, array{mixed, mixed}>
|
||||||
|
*/
|
||||||
|
function reversedEntries(iterable $data): \Generator
|
||||||
|
{
|
||||||
|
if (is_array($data)) {
|
||||||
|
for (end($data); ($key = key($data)) !== null; prev($data)) {
|
||||||
|
yield [$key, current($data)];
|
||||||
|
}
|
||||||
|
} elseif ($data instanceof \Ds\Seq || $data instanceof \Ds\Set) {
|
||||||
|
for ($index = \count($data) - 1; $index >= 0; $index--) {
|
||||||
|
yield [$index, $data->get($index)];
|
||||||
|
}
|
||||||
|
} elseif ($data instanceof \Ds\Map) {
|
||||||
|
foreach ($data->pairs()->reversed() as $pair) {
|
||||||
|
yield [$pair->key, $pair->value];
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
$entries = [];
|
||||||
|
foreach ($data as $key => $value) {
|
||||||
|
$entries[] = [$key, $value];
|
||||||
|
}
|
||||||
|
|
||||||
|
yield from array_reverse($entries);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Shared implementation of {@see first()} and {@see find()}, so that the exception names the called function.
|
||||||
|
*
|
||||||
|
* @internal
|
||||||
|
*
|
||||||
|
* @return \Closure(iterable<mixed, mixed>): mixed
|
||||||
|
*/
|
||||||
|
function firstOf(string $name, ?callable $predicate, bool $required): \Closure
|
||||||
|
{
|
||||||
|
$predicate = $predicate === null ? null : callback($predicate);
|
||||||
|
|
||||||
|
return static function (iterable $data) use ($name, $predicate, $required) {
|
||||||
|
foreach ($data as $key => $value) {
|
||||||
|
if ($predicate === null || $predicate($value, $key)) {
|
||||||
|
return $value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($required) {
|
||||||
|
throw EmptyCollectionException::noMatch($name, $predicate !== null);
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Shared implementation of {@see min()} (`$direction` -1) and {@see max()} (1).
|
||||||
|
*
|
||||||
|
* @internal
|
||||||
|
*
|
||||||
|
* @return \Closure(iterable<mixed, mixed>): mixed
|
||||||
|
*/
|
||||||
|
function extremum(int $direction, ?callable $selector): \Closure
|
||||||
|
{
|
||||||
|
$selector = $selector === null ? static fn ($value) => $value : callback($selector);
|
||||||
|
|
||||||
|
return static function (iterable $data) use ($direction, $selector) {
|
||||||
|
$best = null;
|
||||||
|
$first = true;
|
||||||
|
foreach ($data as $key => $value) {
|
||||||
|
$value = $selector($value, $key);
|
||||||
|
if ($first || ($value <=> $best) === $direction) {
|
||||||
|
$best = $value;
|
||||||
|
$first = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return $best;
|
||||||
|
};
|
||||||
|
}
|
||||||
@ -22,41 +22,11 @@ namespace Kadet\Functional\Collections;
|
|||||||
use Kadet\Functional\Exception\EmptyCollectionException;
|
use Kadet\Functional\Exception\EmptyCollectionException;
|
||||||
|
|
||||||
use function Kadet\Functional\Collections\Internal\callback;
|
use function Kadet\Functional\Collections\Internal\callback;
|
||||||
|
use function Kadet\Functional\Collections\Internal\extremum;
|
||||||
|
use function Kadet\Functional\Collections\Internal\firstOf;
|
||||||
|
use function Kadet\Functional\Collections\Internal\reversedEntries;
|
||||||
use function Kadet\Functional\compile;
|
use function Kadet\Functional\compile;
|
||||||
|
|
||||||
/**
|
|
||||||
* Yields [key, value] pairs of $data from the end, without copying it where the container allows.
|
|
||||||
*
|
|
||||||
* @internal
|
|
||||||
*
|
|
||||||
* @param iterable<mixed, mixed> $data
|
|
||||||
*
|
|
||||||
* @return \Generator<int, array{mixed, mixed}>
|
|
||||||
*/
|
|
||||||
function reversedEntries(iterable $data): \Generator
|
|
||||||
{
|
|
||||||
if (is_array($data)) {
|
|
||||||
for (end($data); ($key = key($data)) !== null; prev($data)) {
|
|
||||||
yield [$key, current($data)];
|
|
||||||
}
|
|
||||||
} elseif ($data instanceof \Ds\Seq || $data instanceof \Ds\Set) {
|
|
||||||
for ($index = \count($data) - 1; $index >= 0; $index--) {
|
|
||||||
yield [$index, $data->get($index)];
|
|
||||||
}
|
|
||||||
} elseif ($data instanceof \Ds\Map) {
|
|
||||||
foreach ($data->pairs()->reversed() as $pair) {
|
|
||||||
yield [$pair->key, $pair->value];
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
$entries = [];
|
|
||||||
foreach ($data as $key => $value) {
|
|
||||||
$entries[] = [$key, $value];
|
|
||||||
}
|
|
||||||
|
|
||||||
yield from array_reverse($entries);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the first value for which `$predicate($value, $key)` is truthy, or the first value without a predicate.
|
* Returns the first value for which `$predicate($value, $key)` is truthy, or the first value without a predicate.
|
||||||
*
|
*
|
||||||
@ -145,32 +115,6 @@ function find(callable $predicate, bool $required = false): \Closure
|
|||||||
return firstOf('find', $predicate, $required);
|
return firstOf('find', $predicate, $required);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Shared implementation of {@see first()} and {@see find()}, so that the exception names the called function.
|
|
||||||
*
|
|
||||||
* @internal
|
|
||||||
*
|
|
||||||
* @return \Closure(iterable<mixed, mixed>): mixed
|
|
||||||
*/
|
|
||||||
function firstOf(string $name, ?callable $predicate, bool $required): \Closure
|
|
||||||
{
|
|
||||||
$predicate = $predicate === null ? null : callback($predicate);
|
|
||||||
|
|
||||||
return static function (iterable $data) use ($name, $predicate, $required) {
|
|
||||||
foreach ($data as $key => $value) {
|
|
||||||
if ($predicate === null || $predicate($value, $key)) {
|
|
||||||
return $value;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($required) {
|
|
||||||
throw EmptyCollectionException::noMatch($name, $predicate !== null);
|
|
||||||
}
|
|
||||||
|
|
||||||
return null;
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Whether the collection holds `$value`, compared strictly (`Ds\Key::equals` when `$value` implements `Ds\Key`).
|
* Whether the collection holds `$value`, compared strictly (`Ds\Key::equals` when `$value` implements `Ds\Key`).
|
||||||
*
|
*
|
||||||
@ -330,32 +274,6 @@ function max(?callable $selector = null): \Closure
|
|||||||
return extremum(1, $selector);
|
return extremum(1, $selector);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Shared implementation of {@see min()} (`$direction` -1) and {@see max()} (1).
|
|
||||||
*
|
|
||||||
* @internal
|
|
||||||
*
|
|
||||||
* @return \Closure(iterable<mixed, mixed>): mixed
|
|
||||||
*/
|
|
||||||
function extremum(int $direction, ?callable $selector): \Closure
|
|
||||||
{
|
|
||||||
$selector = $selector === null ? static fn ($value) => $value : callback($selector);
|
|
||||||
|
|
||||||
return static function (iterable $data) use ($direction, $selector) {
|
|
||||||
$best = null;
|
|
||||||
$first = true;
|
|
||||||
foreach ($data as $key => $value) {
|
|
||||||
$value = $selector($value, $key);
|
|
||||||
if ($first || ($value <=> $best) === $direction) {
|
|
||||||
$best = $value;
|
|
||||||
$first = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return $best;
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Folds the collection into a single value with `$fn($carry, $value, $key)`, starting from `$initial`.
|
* Folds the collection into a single value with `$fn($carry, $value, $key)`, starting from `$initial`.
|
||||||
*
|
*
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user