Comment puis-je supprimer les valeurs en double d'un tableau multidimensionnel en PHP?
Exemple de tableau:
Array
(
[0] => Array
(
[0] => abc
[1] => def
)
[1] => Array
(
[0] => ghi
[1] => jkl
)
[2] => Array
(
[0] => mno
[1] => pql
)
[3] => Array
(
[0] => abc
[1] => def
)
[4] => Array
(
[0] => ghi
[1] => jkl
)
[5] => Array
(
[0] => mno
[1] => pql
)
)
Voici un autre moyen. Aucune variable intermédiaire n'est enregistrée.
Nous avons utilisé cela pour dédoubler les résultats d'une variété de requêtes se chevauchant.
$input = array_map("unserialize", array_unique(array_map("serialize", $input)));
Depuis la version 5.2.9, vous pouvez utiliser array_unique()
si vous utilisez le drapeau SORT_REGULAR
comme suit:
array_unique($array, SORT_REGULAR);
Cela rend la fonction comparer les éléments pour l’égalité comme si $a == $b
était utilisé, ce qui est parfait pour votre cas.
Sortie
Array
(
[0] => Array
(
[0] => abc
[1] => def
)
[1] => Array
(
[0] => ghi
[1] => jkl
)
[2] => Array
(
[0] => mno
[1] => pql
)
)
Gardez toutefois à l'esprit que la documentation indique:
array_unique()
n'est pas destiné à fonctionner sur des tableaux multidimensionnels.
J'ai eu un problème similaire mais j'ai trouvé une solution efficace à 100%.
<?php
function super_unique($array,$key)
{
$temp_array = [];
foreach ($array as &$v) {
if (!isset($temp_array[$v[$key]]))
$temp_array[$v[$key]] =& $v;
}
$array = array_values($temp_array);
return $array;
}
$arr="";
$arr[0]['id']=0;
$arr[0]['titel']="ABC";
$arr[1]['id']=1;
$arr[1]['titel']="DEF";
$arr[2]['id']=2;
$arr[2]['titel']="ABC";
$arr[3]['id']=3;
$arr[3]['titel']="XYZ";
echo "<pre>";
print_r($arr);
echo "unique*********************<br/>";
print_r(super_unique($arr,'titel'));
?>
Autrement. Préserve les clés aussi.
function array_unique_multidimensional($input)
{
$serialized = array_map('serialize', $input);
$unique = array_unique($serialized);
return array_intersect_key($input, $unique);
}
Les commentaires de l'utilisateur sur la documentation array_unique () apportent de nombreuses solutions. Voici l'un d'entre eux:
kenrbnsn à rbnsn dot com
27 sept. 2005 12:09Encore un autre Array_Unique pour les tableaux multi-tensions. Je n’ai testé cela que sur des tableaux à deux divisions, mais cela pourrait probablement être généralisé pour davantage, ou utiliser la récursion.
Cette fonction utilise les fonctions serialize, array_unique et unserialize pour effectuer le travail.
function multi_unique($array) { foreach ($array as $k=>$na) $new[$k] = serialize($na); $uniq = array_unique($new); foreach($uniq as $k=>$ser) $new1[$k] = unserialize($ser); return ($new1); }
Ceci est de http://ca3.php.net/manual/en/function.array-unique.php#57202 .
Si "supprimer les doublons" signifie "supprimer les doublons, mais en laisser un", une solution pourrait consister à appliquer d'abord array_unique(...)
sur la "colonne d'identificateur", puis à supprimer dans le tableau d'origine toutes les clés déjà utilisées. retiré du tableau de colonnes:
$array = [
[
'id' => '123',
'foo' => 'aaa',
'bar' => 'bbb'
],
[
'id' => '123',
'foo' => 'ccc',
'bar' => 'ddd'
],
[
'id' => '567',
'foo' => 'eee',
'bar' => 'fff'
]
];
$ids = array_column($array, 'id');
$ids = array_unique($ids);
$array = array_filter($array, function ($key, $value) use ($ids) {
return in_array($value, array_keys($ids));
}, ARRAY_FILTER_USE_BOTH);
Le résultat est:
Array
(
[0] => Array
(
[id] => 123
[foo] => aaa
[bar] => bbb
)
[2] => Array
(
[id] => 567
[foo] => eee
[bar] => fff
)
)
Array
(
[0] => Array
(
[id] => 1
[name] => john
)
[1] => Array
(
[id] => 2
[name] => smith
)
[2] => Array
(
[id] => 3
[name] => john
)
[3] => Array
(
[id] => 4
[name] => robert
)
)
$temp = array_unique(array_column($array, 'name'));
$unique_arr = array_intersect_key($array, $temp);
Cela supprimera les noms en double du tableau. unique par clé
si vous avez besoin d'éliminer les doublons sur des clés spécifiques, telles qu'un identifiant mysqli, voici une fonction simple
function search_array_compact($data,$key){
$compact = [];
foreach($data as $row){
if(!in_array($row[$key],$compact)){
$compact[] = $row;
}
}
return $compact;
}
Points bonus Vous pouvez passer un tableau de clés et en ajouter une autre, mais ce sera 2 fois plus lent par clé supplémentaire.
Utilisez simplement l'option SORT_REGULAR comme second paramètre.
$uniqueArray = array_unique($array, SORT_REGULAR);
si vous avez un tableau comme celui-ci:
(utilisateurs est le nom du tableau)
Array=>
[0] => (array)
'user' => 'john'
'age' => '23'
[1] => (array)
'user' => 'jane'
'age' => '20'
[2]=> (array)
'user' => 'john'
'age' => '23'
et vous voulez supprimer les doublons ... alors:
$serialized = array();
for ($i=0; $i < sizeof($users); $i++) {
$test = in_array($users['user'], $serialized);
if ($test == false) {
$serialized[] = $users['user'];
}
}
peut être une solution: P
Une solution facile à lire, probablement pas la plus efficace:
function arrayUnique($myArray){
if(!is_array($myArray))
return $myArray;
foreach ($myArray as &$myvalue){
$myvalue=serialize($myvalue);
}
$myArray=array_unique($myArray);
foreach ($myArray as &$myvalue){
$myvalue=unserialize($myvalue);
}
return $myArray;
}
Voici un moyen très simple et logique de créer un tableau multi-dimensionnel comme suit:
Si vous avez un tableau comme celui-ci:
Array
(
[Key1] => Array
(
[0] => Value1
[1] => Value2
[2] => Value1
[3] => Value3
[4] => Value1
)
[Key2] => Array
(
[0] => Value1
[1] => Value2
[2] => Value1
[3] => Value3
[4] => Value4
)
)
utilisez foreach
pour résoudre ceci:
foreach($array as $k=>$v){
$unique=array_unique($v);
$array[$k]=$unique;
}
cela vous donnera le résultat suivant:
Array
(
[Key1] => Array
(
[0] => Value1
[1] => Value2
[3] => Value3
)
[Key2] => Array
(
[0] => Value1
[1] => Value2
[3] => Value3
[4] => Value4
)
)
et si vous voulez réorganiser l'ordre des touches,
foreach($array as $k=>$v){
$unique= array_values(array_unique($v));
$array[$k]=$unique;
}
Cette opération vous donnera les valeurs clés arrangées comme ceci:
Array
(
[Key1] => Array
(
[0] => Value1
[1] => Value2
[2] => Value3
)
[Key2] => Array
(
[0] => Value1
[1] => Value2
[2] => Value3
[3] => Value4
)
)
J'espère que ça va tout effacer.
Beaucoup de personnes m'ont demandé comment créer un tableau multidimensionnel unique. J'ai pris référence à votre commentaire et cela m'aide.
Tout d’abord, merci à @jeromegamez @daveilers pour votre solution. Mais chaque fois que j'ai donné la réponse, ils m'ont demandé comment cela fonctionne: "sérialiser" et "désérialiser". C'est pourquoi je veux partager la raison de ceci avec vous afin que cela aide plus de gens à comprendre le concept derrière tout cela.
J'explique pourquoi nous utilisons 'sérialiser' et 'désérialiser' par étapes:
Étape 1: convertissez le tableau multidimensionnel en tableau unidimensionnel
Pour convertir le tableau multidimensionnel en un tableau unidimensionnel, commencez par générer une représentation sous forme de flux d'octets de tous les éléments (y compris les tableaux imbriqués) à l'intérieur du tableau. La fonction serialize () peut générer une représentation sous forme de flux d'octets d'une valeur. Pour générer une représentation de flux d'octets de tous les éléments, appelez la fonction serialize () dans la fonction array_map () en tant que fonction de rappel. Le résultat sera un tableau unidimensionnel, quel que soit le nombre de niveaux du tableau multidimensionnel.
Étape 2: Rendre les valeurs uniques
Pour rendre ce tableau unidimensionnel unique, utilisez la fonction array_unique ().
Étape 3: revenez au tableau multidimensionnel
Bien que le tableau soit maintenant unique, les valeurs ressemblent à une représentation de flux d'octets. Pour revenir au tableau multidimensionnel, utilisez la fonction unserialize ().
$input = array_map("unserialize", array_unique(array_map("serialize", $input)));
Merci encore pour tout ça.
J'ai longuement réfléchi à ce problème et déterminé que la solution optimale devait suivre deux règles.
Dans cet esprit, et compte tenu de toutes les bizarreries de PHP, voici la solution que j'ai proposée. Contrairement à certaines des autres réponses, il est possible de supprimer des éléments en fonction de la ou des clés souhaitées. Le tableau en entrée devrait être composé de clés numériques.
$count_array = count($input);
for ($i = 0; $i < $count_array; $i++) {
if (isset($input[$i])) {
for ($j = $i+1; $j < $count_array; $j++) {
if (isset($input[$j])) {
//this is where you do your comparison for dupes
if ($input[$i]['checksum'] == $input[$j]['checksum']) {
unset($input[$j]);
}
}
}
}
}
Le seul inconvénient est que les clés ne sont pas en ordre à la fin de l'itération. Ce n'est pas un problème si, par la suite, vous utilisez uniquement des boucles foreach, mais si vous devez utiliser une boucle for, vous pouvez mettre $input = array_values($input);
après ce qui précède pour renuméroter les clés.
Si vous avez un tableau comme celui-ci
data = array
(
[0] => array
(
[subject] => a
[object] => c
),
[1] => array
(
[subject] => b
[object] => d
),
[2] => array
(
[subject] => d
[object] => b
),
[3] => array
(
[subject] => d
[object] => c
),
[4] => array
(
[subject] => c
[object] => a
),
[5] => array
(
[subject] => c
[object] => d
)
)
et vous voulez obtenir des tableaux comme celui-ci:
data = array
(
[0] => array
(
[subject] => a
[object] => c
),
[1] => array
(
[subject] => b
[object] => d
),
[2] => array
(
[subject] => d
[object] => c
)
)
ou
data = array
(
[0] => array
(
[subject] => d
[object] => b
),
[1] => array
(
[subject] => c
[object] => a
),
[2] => array
(
[subject] => c
[object] => d
)
)
un code suivant peut aider
$data1 = array();
$data1 = $data;
for($q=0;$q<count($data);$q++)
{
for($p=0;$p<count($data1);$p++)
{
if (($data[$q]["subject"] == $data1[$p]["object"]) && ($data[$q]["object"] == $data1[$p]["subject"]))
{
$data1[$p]["subject"] = $data[$q]["subject"];
$data1[$p]["object"] = $data[$q]["object"];
}
}
}
$data1 = array_values(array_map("unserialize", array_unique(array_map("serialize", $data1))));
$data = $data1;
Une alternative à la sérialisation et unique
$test = [
['abc','def'],
['ghi','jkl'],
['mno','pql'],
['abc','def'],
['ghi','jkl'],
['mno','pql'],
];
$result = array_reduce(
$test,
function($carry,$item){
if(!in_array($item,$carry)) {
array_Push($carry,$item);
}
return $carry;
},
[]
);
var_dump($result);
/*
php unique.php
array(3) {
[0] =>
array(2) {
[0] =>
string(3) "abc"
[1] =>
string(3) "def"
}
[1] =>
array(2) {
[0] =>
string(3) "ghi"
[1] =>
string(3) "jkl"
}
[2] =>
array(2) {
[0] =>
string(3) "mno"
[1] =>
string(3) "pql"
}
}
* /
Comme les gens disent que array_unique()
est très lent, voici un extrait de code que j'utilise pour un tableau multidimensionnel à un niveau.
$serialized_array = array_map("serialize", $input);
foreach ($serialized_array as $key => $val) {
$result[$val] = true;
}
$output = array_map("unserialize", (array_keys($result)));
Note de référence du premier utilisateur ayant contribué à la note de array_unique()
page de fonction dans php.net