1. GROUP BY
1 つのキー
この関数GROUP BY
は配列と同様に機能しますが、重要な制限が 1 つあります。グループ化できる「列」は 1 つだけです ( $identifier
)。
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. テーブル (2 次元配列) の一意の行の検出
この関数は、「行」をフィルタリングするためのものです。2 次元配列がテーブルであるとすれば、その各要素は行です。したがって、この関数を使用して重複した行を削除できます。すべての列 (2 番目の次元の要素) が等しい場合、2 つの行 (1 番目の次元の要素) は等しいと見なされます。「列」値の比較に適用されます。値が単純型の場合、値自体が比較に使用されます。それ以外の場合は、そのタイプ ( array
、object
、resource
、unknown type
) が使用されます。
戦略は簡単です。元の配列から、要素がimplode
元の配列の「列」である浅い配列を作成します。それを適用array_unique(...)
します。最後に、検出された ID を元の配列のフィルタリングに使用します。
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;
}
タイプが の場合、「列」値のクラスを検出して比較を改善することもできますobject
。
は$implodeSeparator
多かれ少なかれ複雑な zB である必要がありますspl_object_hash($this)
。
3. テーブル(二次元配列)の一意識別子列を持つ行を検出する
このソリューションは、2 番目のソリューションに依存しています。完全な「行」が一意である必要はありません。1 つの「行」の関連するすべての「フィールド」(2 番目の次元の要素) が対応する「フィールド」(同じキーを持つ要素) と等しい場合、2 つの「行」(最初の次元の要素) は等しくなります。
「関連する」「フィールド」は、渡された「識別子」の要素の 1 つに等しいキーを持つ「フィールド」(2 番目の次元の要素) です。
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;
}