1. GROUP BY
une clé
Cette fonction fonctionne comme GROUP BY
pour le tableau, mais avec une limitation importante : Une seule "colonne" de regroupement ( $identifier
) est possible.
function arrayUniqueByIdentifier(array $array, string $identifier)
{
$ids = array_column($array, $identifier);
$ids = array_unique($ids);
$array = array_filter($array,
function ($key, $value) use($ids) {
return in_array($value, array_keys($ids));
}, ARRAY_FILTER_USE_BOTH);
return $array;
}
2. Détecter les lignes uniques d'un tableau (tableau bidimensionnel)
Cette fonction permet de filtrer les "rangées". Si nous disons qu'un tableau à deux dimensions est un tableau, alors chaque élément est une ligne. Cette fonction permet donc d'éliminer les lignes dupliquées. Deux lignes (éléments de la première dimension) sont égales, si toutes leurs colonnes (éléments de la deuxième dimension) sont égales. La comparaison des valeurs "colonnes" s'applique : Si une valeur est d'un simple type la valeur elle-même sera utilisée pour la comparaison ; sinon, son type ( array
, object
, resource
, unknown type
) seront utilisés.
La stratégie est simple : Créer à partir du tableau original un tableau peu profond, dont les éléments sont implode
d "colonnes" du tableau original ; puis appliquer array_unique(...)
et enfin, utiliser les identifiants détectés pour filtrer le tableau original.
function arrayUniqueByRow(array $table = [], string $implodeSeparator)
{
$elementStrings = [];
foreach ($table as $row) {
// To avoid notices like "Array to string conversion".
$elementPreparedForImplode = array_map(
function ($field) {
$valueType = gettype($field);
$simpleTypes = ['boolean', 'integer', 'double', 'float', 'string', 'NULL'];
$field = in_array($valueType, $simpleTypes) ? $field : $valueType;
return $field;
}, $row
);
$elementStrings[] = implode($implodeSeparator, $elementPreparedForImplode);
}
$elementStringsUnique = array_unique($elementStrings);
$table = array_intersect_key($table, $elementStringsUnique);
return $table;
}
Il est également possible d'améliorer la comparaison, en détectant la classe de la valeur "colonne", si son type est object
.
En $implodeSeparator
devrait être plus ou moins complexe, z.B. spl_object_hash($this)
.
3. Détection des lignes avec des colonnes d'identification uniques pour une table (tableau bidimensionnel)
Cette solution repose sur la deuxième solution. Maintenant, la "rangée" complète n'a pas besoin d'être unique. Deux "rangées" (éléments de la première dimension) sont égales maintenant, si tous les éléments de la première dimension sont uniques. pertinent Les "champs" (éléments de la deuxième dimension) d'une "ligne" sont égaux aux "champs" correspondants (éléments ayant la même clé).
Les "champs" "pertinents" sont les "champs" (éléments de la deuxième dimension) dont la clé est égale à l'un des éléments des "identifiants" passés.
function arrayUniqueByMultipleIdentifiers(array $table, array $identifiers, string $implodeSeparator = null)
{
$arrayForMakingUniqueByRow = $removeArrayColumns($table, $identifiers, true);
$arrayUniqueByRow = $arrayUniqueByRow($arrayForMakingUniqueByRow, $implodeSeparator);
$arrayUniqueByMultipleIdentifiers = array_intersect_key($table, $arrayUniqueByRow);
return $arrayUniqueByMultipleIdentifiers;
}
function removeArrayColumns(array $table, array $columnNames, bool $isWhitelist = false)
{
foreach ($table as $rowKey => $row) {
if (is_array($row)) {
if ($isWhitelist) {
foreach ($row as $fieldName => $fieldValue) {
if (!in_array($fieldName, $columnNames)) {
unset($table[$rowKey][$fieldName]);
}
}
} else {
foreach ($row as $fieldName => $fieldValue) {
if (in_array($fieldName, $columnNames)) {
unset($table[$rowKey][$fieldName]);
}
}
}
}
}
return $table;
}