intégrer les méthodes de Cursor et KeyAccess

This commit is contained in:
Jephté Clain 2025-05-09 10:27:06 +04:00
parent dd3006e05d
commit 8e7e59cc42
2 changed files with 186 additions and 7 deletions

View File

@ -1,6 +1,7 @@
<?php
namespace nulib;
use nulib\php\func;
use Traversable;
/**
@ -232,4 +233,111 @@ class A {
if ($assoc) uasort($array, cl::compare($keys));
else usort($array, cl::compare($keys));
}
#############################################################################
/**
* s'assurer que $array est un tableau associatif, en remplaçant toutes les
* clés numériques par la clé correspondante dans $key
* <code>
* $array = ["first", "second"]
* A::ensure_assoc($array, ["a", "b"]);
* // returns ["a" => "first", "b" => "second"]
* </code>
*/
static final function ensure_assoc(?array &$array, array $keys, ?array $params=null): void {
$prefix = $params["key_prefix"] ?? null;
$suffix = $params["key_suffix"] ?? null;
$index = 0;
foreach ($keys as $key) {
if ($prefix !== null || $suffix !== null) {
$destKey = "$prefix$key$suffix";
} else {
# préserver les clés numériques
$destKey = $key;
}
if ($array !== null && array_key_exists($destKey, $array)) continue;
while (in_array($index, $keys, true)) {
$index++;
}
if ($array !== null && array_key_exists($index, $array)) {
$array[$destKey] = $array[$index];
unset($array[$index]);
$index++;
}
}
}
/**
* s'assurer que $array contient toutes les clés de $defaults, avec la valeur
* par défaut le cas échéant
*
* $missings est un tableau indiquant des valeurs qui si elles sont dans
* $array, signifie que la clé correspondante doit être considérée comme
* inexistante (et donc remplacée par la valeur de $defaults)
*/
static final function ensure_keys(?array &$array, array $defaults, ?array $missings=null, ?array $params=null): void {
$keys = array_keys($defaults);
$prefix = $params["key_prefix"] ?? null;
$suffix = $params["key_suffix"] ?? null;
foreach ($keys as $key) {
$destKey = "$prefix$key$suffix";
$haveMissing = $missings !== null && array_key_exists($key, $missings);
if ($array === null || !array_key_exists($destKey, $array)) {
$array[$destKey] = $defaults[$key];
} elseif ($haveMissing && $array[$destKey] === $missings[$key]) {
$array[$destKey] = $defaults[$key];
}
}
}
/**
* supprimer dans $array les clés dont les valeurs correspondent au tableau
* $missings
*/
static final function delete_missings(?array &$array, array $missings, ?array $params=null): void {
$prefix = $params["key_prefix"] ?? null;
$suffix = $params["key_suffix"] ?? null;
foreach ($missings as $key => $missing) {
$destKey = "$prefix$key$suffix";
if (array_key_exists($destKey, $array) && $array[$destKey] === $missing) {
unset($array[$destKey]);
}
}
}
/**
* s'assurer que les clés dans $array sont dans le même ordre que dans $keys
*
* les clés supplémentaires sont poussées à la fin du tableau
*/
static final function ensure_order(?array &$array, array $keys, ?array $params=null): void {
if ($array === null) return;
$prefix = $params["key_prefix"] ?? null;
$suffix = $params["key_suffix"] ?? null;
if ($prefix !== null || $suffix !== null) {
foreach ($keys as &$key) {
$key = "$prefix$key$suffix";
}; unset($key);
}
$destKeys = array_keys($array);
$keyCount = count($keys);
if (array_slice($destKeys, 0, $keyCount) === $keys) {
# si le tableau a déjà les bonnes clés dans le bon ordre, rien à faire
return;
}
$ordered = [];
foreach ($keys as $key) {
if (array_key_exists($key, $array)) {
$ordered[$key] = $array[$key];
unset($array[$key]);
}
}
$preserveKeys = $params["preserve_keys"] ?? false;
if ($preserveKeys) $array = cl::merge2($ordered, $array);
else $array = array_merge($ordered, $array);
}
}

View File

@ -398,15 +398,86 @@ class cl {
#############################################################################
static final function map($func, ?iterable $array): array {
$result = [];
if ($array !== null) {
$func = func::with($func);
foreach ($array as $key => $value) {
$result[$key] = $func->invoke([$value, $key]);
/**
* tester si $array satisfait les conditions de $filter
* - $filter est un scalaire, le transformer en [$filter]
* - sinon $filter doit être un tableau de scalaires
*
* les règles des conditions sont les suivantes:
* - une valeur séquentielle $key est équivalente à la valeur associative
* $key => true
* - une valeur associative $key => bool indique que la clé correspondante ne
* doit pas (resp. doit) exister selon que bool vaut false (resp. true)
* - une valeur associative $key => $value indique que la clé correspondante
* doit exiter avec la valeur spécifiée
*/
static final function filter(?array $array, $filter): bool {
if ($filter === null) return false;
if (!is_array($filter)) $filter = [$filter];
if (!$filter) return false;
$index = 0;
foreach ($filter as $key => $value) {
if ($key === $index) {
$index++;
if ($array === null) return false;
if (!array_key_exists($value, $array)) return false;
} elseif (is_bool($value)) {
if ($value) {
if ($array === null || !array_key_exists($key, $array)) return false;
} else {
if ($array !== null && array_key_exists($key, $array)) return false;
}
} else {
if ($array === null) return false;
if (!array_key_exists($key, $array)) return false;
if ($array[$key] !== $value) return false;
}
}
return $result;
return true;
}
/**
* mapper le tableau source $array selon les règles suivantes illustrées dans
* l'exemple suivant:
* si
* $map = ["a", "b" => "x", "c" => function() { return "y"; }, "d" => null]
* alors retourner le tableau
* ["a" => $array["a"], "b" => $array["x"], "c" => "y", "d" => null]
*
* si une fonction est utilisée, sa signature est
* <code>function(mixed $value, string|int $key, ?array $array)</code>
*/
static function map(?array $array, ?array $map): ?array {
if ($map === null) return $array;
$index = 0;
$mapped = [];
foreach ($map as $key => $value) {
if ($key === $index) {
$index++;
if ($value === null) $mapped[] = null;
else $mapped[$value] = cl::get($array, $value);
} elseif (is_callable($value)) {
$func = func::with($value);
$value = cl::get($array, $key);
$mapped[$key] = $func->invoke([$value, $key, $array]);
} else {
if ($value === null) $mapped[$key] = null;
else $mapped[$key] = cl::get($array, $value);
}
}
return $mapped;
}
static final function mapf(?iterable $items, $func): array {
$mapped = [];
if ($items !== null) {
$func = func::with($func);
foreach ($items as $key => $item) {
$mapped[$key] = $func->invoke([$item, $key, $items]);
}
}
return $mapped;
}
#############################################################################