Comment puis-je utiliser array_unique sur un tableau de tableaux?
-
23-09-2019 - |
Question
J'ai un tableau
Array(
[0] => Array
(
[0] => 33
[user_id] => 33
[1] => 3
[frame_id] => 3
)
[1] => Array
(
[0] => 33
[user_id] => 33
[1] => 3
[frame_id] => 3
)
[2] => Array
(
[0] => 33
[user_id] => 33
[1] => 8
[frame_id] => 8
)
[3] => Array
(
[0] => 33
[user_id] => 33
[1] => 3
[frame_id] => 3
)
[4] => Array
(
[0] => 33
[user_id] => 33
[1] => 3
[frame_id] => 3
)
)
Comme vous pouvez le voir sur la touche 0 est le même que 1, 3 et 4. Et la clé 2 est différent de tous.
Lors de l'exécution de la fonction array_unique sur eux, la gauche est seulement
Array (
[0] => Array
(
[0] => 33
[user_id] => 33
[1] => 3
[frame_id] => 3
)
)
Toutes les idées pourquoi array_unique ne fonctionne pas comme prévu?
La solution
Il est parce que array_unique
compare éléments à l'aide d'une comparaison de chaînes. De la docs :
Note: Deux éléments sont considérés égaux si et seulement si (string) $ elem1 === (string) $ elem2. En d'autres termes: lorsque la représentation de chaîne est le même. Le premier élément sera utilisé.
La représentation de chaîne d'un tableau est simplement le mot Array
, peu importe son contenu.
Vous pouvez faire ce que vous voulez faire en utilisant les éléments suivants:
$arr = array(
array('user_id' => 33, 'frame_id' => 3),
array('user_id' => 33, 'frame_id' => 3),
array('user_id' => 33, 'frame_id' => 8)
);
$arr = array_intersect_key($arr, array_unique(array_map('serialize', $arr)));
//result:
array
0 =>
array
'user_id' => int 33
'user' => int 3
2 =>
array
'user_id' => int 33
'user' => int 8
Voilà comment cela fonctionne:
-
Chaque élément du tableau est sérialisé. Cette sera unique basé sur le tableau de contenu.
-
Les résultats de ce sont gérés par
array_unique
, de sorte que des tableaux uniques avec signatures sont laissés. -
array_intersect_key
prendra les clés des éléments uniques de la fonction de carte unique / (sont conservés depuis les clés du tableau source) et tirez les de votre source d'origine matrice.
Autres conseils
array_unique()
ne supporte que les tableaux multidimensionnels en PHP 5.2.9 et supérieur.
Au lieu de cela, vous pouvez créer un hachage du tableau et vérifier pour-ness unique.
$hashes = array();
foreach($array as $val) {
$hashes[md5(serialize($val))] = $val;
}
array_unique($hashes);
Voici une version améliorée de réponse @ ryeguy :
<?php
$arr = array(
array('user_id' => 33, 'tmp_id' => 3),
array('user_id' => 33, 'tmp_id' => 4),
array('user_id' => 33, 'tmp_id' => 5)
);
# $arr = array_intersect_key($arr, array_unique(array_map('serialize', $arr)));
$arr = array_intersect_key($arr, array_unique(array_map(function ($el) {
return $el['user_id'];
}, $arr)));
//result:
array
0 =>
array
'user_id' => int 33
'tmp_id' => int 3
D'abord, il ne fait pas sérialisation inutile. En second lieu, les attributs parfois peut être différent même si id est le même.
J'ai rencontré avec API Google Places . Je panachage des résultats de plusieurs requêtes avec différents types d'objets (pensez balises). Mais je suis en double, car un objet peut être mis en plusieurs catégories (types). Et la méthode avec serialize
ne fonctionnait pas, puisque les attrs étaient différents, à savoir, photo_reference
et reference
. Probablement ceux-ci sont comme ids temporaires.
array_unique ne fonctionne pas récursif, il pense juste « ce sont tous les Array
s, nous allons tuer tous mais ... on y va! »
Réponse rapide (TL; DR)
- valeurs distinctes peuvent être extraites de tableau PHP de AssociativeArrays utilisant foreach
- Ceci est une approche simpliste
Réponse détaillée
Contexte
- PHP 5.3
- Array PHP de AssociativeArrays (tabluar variable de données composite)
- Autre nom pour cette variable composite est ArrayOfDictionary (AOD)
Problème
- Scénario: DeveloperMarsher a une variable composite sous forme de tableau PHP
- DeveloperMarsher souhaite extraire des valeurs distinctes sur une paire valeur de nom spécifique
- Dans l'exemple ci-dessous, DeveloperMarsher souhaite obtenir des lignes pour chaque distincte paire valeur du nom de
fname
Solution
-
example01 ;; DeveloperMarsher commence par une variable de données tabluar qui ressemble à ceci
$aodtable = json_decode('[ { "fname": "homer" ,"lname": "simpson" }, { "fname": "homer" ,"lname": "jackson" }, { "fname": "homer" ,"lname": "johnson" }, { "fname": "bart" ,"lname": "johnson" }, { "fname": "bart" ,"lname": "jackson" }, { "fname": "bart" ,"lname": "simpson" }, { "fname": "fred" ,"lname": "flintstone" } ]',true);
-
example01 ;; DeveloperMarsher peut extraire des valeurs distinctes avec une boucle foreach qui suit les valeurs vu
$sgfield = 'fname'; $bgnocase = true; // $targfield = $sgfield; $ddseen = Array(); $vout = Array(); foreach ($aodtable as $datarow) { if( (boolean) $bgnocase == true ){ @$datarow[$targfield] = @strtolower($datarow[$targfield]); } if( (string) @$ddseen[ $datarow[$targfield] ] == '' ){ $rowout = array_intersect_key($datarow, array_flip(array_keys($datarow))); $ddseen[ $datarow[$targfield] ] = $datarow[$targfield]; $vout[] = Array( $rowout ); } } //;; print var_export( $vout, true );
Résultat de sortie
array ( 0 => array ( 0 => array ( 'fname' => 'homer', 'lname' => 'simpson', ), ), 1 => array ( 0 => array ( 'fname' => 'bart', 'lname' => 'johnson', ), ), 2 => array ( 0 => array ( 'fname' => 'fred', 'lname' => 'flintstone', ), ), )
Pitfalls
- Cette solution ne regroupe pas sur les champs qui ne font pas partie de l'opération DISTINCT
- paires nom-valeur arbitraire sont retournés à partir des lignes distinctes choisies arbitrairement
- ordre de tri arbitraire de la production
- Gestion arbitraire de la lettre cas (majuscule est distinct de minuscules a?)
Voir aussi
- php array_intersect_key
- php array_flip
function array_unique_recursive($array)
{
$array = array_unique($array, SORT_REGULAR);
foreach ($array as $key => $elem) {
if (is_array($elem)) {
$array[$key] = array_unique_recursive($elem);
}
}
return $array;
}
Ne pas faire l'affaire?