Wie kann ich array_unique auf ein Array von Arrays verwenden?
-
23-09-2019 - |
Frage
Ich habe ein Array
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
)
)
Wie Sie die Taste 0 sehen kann, ist die gleiche wie 1, 3 und 4. Und Taste 2 unterscheidet sich von allen.
Wenn ihnen die array_unique Funktion ausgeführt wird, die nur links
Array (
[0] => Array
(
[0] => 33
[user_id] => 33
[1] => 3
[frame_id] => 3
)
)
Irgendwelche Ideen, warum array_unique wird nicht wie erwartet funktioniert?
Lösung
Es ist, weil array_unique
Artikel vergleicht einen String-Vergleich verwenden. Von der docs :
Hinweis: Zwei Elemente werden als gleich, wenn und nur wenn (string) $ elem1 === (string) $ elem2. In Worten: Wenn die String-Darstellung ist das gleiche. Das erste Element verwendet werden.
Die Stringdarstellung eines Arrays ist einfach das Wort Array
, egal was ihr Inhalt ist.
Sie können tun, was Sie mit dem folgenden tun:
$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
Hier ist, wie es funktioniert:
-
Jedes Array-Element wird serialisiert. Dies wird auf der Grundlage der Arrays eindeutig sein Inhalt.
-
Die Ergebnisse dieser durch
array_unique
laufen, so nur Arrays mit einzigartigen Unterschriften gelassen werden. -
array_intersect_key
nehmen die Schlüssel der Unikate aus die Karte / einzigartige Funktion (da die Schlüssel des Quell-Arrays erhalten bleiben) und Pull sie aus Ihrer ursprünglichen Quelle Array.
Andere Tipps
array_unique()
unterstützt nur mehrdimensionale Arrays in PHP 5.2.9 und höher.
Sie können stattdessen einen Hash-Wert des Array erstellen und überprüfen Sie es auf einzigartige-ness.
$hashes = array();
foreach($array as $val) {
$hashes[md5(serialize($val))] = $val;
}
array_unique($hashes);
Hier ist eine verbesserte Version von @ ryeguy Antwort :
<?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
Als erstes ist es nicht unnötige Serialisierung tun. Zweitens manchmal Attribute sein können unterschiedlich sogar so id gleich ist.
Ich habe in sie laufen mit Google Places API . Ich war Ergebnisse mehrerer Anfragen mit verschiedenen Arten von Objekten (man denke Tags) zu kombinieren. Aber ich habe Duplikate, da ein Objekt in mehrere Gruppen unterteilt werden können (Typen). Und die Methode mit serialize
funktionierte nicht, da die attrs verschieden waren, nämlich photo_reference
und reference
. Wahrscheinlich sind diese wie temporäre IDs.
array_unique deosn't Arbeit rekursiv, so dass es nur denkt „das alle Array
s sind, lassen Sie uns töten alle bis auf einen ... hier gehen wir!“
Schnelle Antwort (TL; DR)
- Ausgeprägte Werte können von PHP Array von AssociativeArrays mit foreach extrahiert werden
- Dies ist ein vereinfachenden Ansatz
Detaillierte Antwort
Kontext
- PHP 5.3
- PHP Array von AssociativeArrays (tabluar zusammengesetzten Datenvariable)
- Alternate Name für diese Verbund Variable ArrayOfDictionary (AOD)
Problem
- Szenario: DeveloperMarsher hat eine PHP tabellarisch zusammengesetzter Variable
- DeveloperMarsher wünscht unterschiedliche Werte auf einem bestimmten Namen-Wert-Paar extrahieren
- Im Beispiel unten, DeveloperMarsher wünscht Zeilen für jedes einzelnes
fname
Name-Wert-Paar erhalten
Lösung
-
EXAMPLE01 ;; DeveloperMarsher beginnt mit einem tabluar Datenvariable, die wie folgt aussieht
$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 können unterschiedliche Werte mit einer foreach Schleife extrahieren, die Spuren gesehen Werte
$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 );
Ausgabeer
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
- Diese Lösung funktioniert nicht Aggregat auf Felder, die nicht Teil der DISTINCT-Operation sind
- beliebige Name-Wert-Paare werden aus willkürlich gewählten unterschiedlichen Zeilen zurück
- Frei wählbare Sortierreihenfolge der Ausgabe
- Willkürliche Umgang mit Brieftasche (ist Kapital A unterscheidet sich von Klein a?)
Siehe auch
- 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;
}
nicht, dass der Trick?