W3docs

array_udiff_uassoc in PHP verwenden

Erfahren Sie, wie Sie die PHP-Funktion array_udiff_uassoc nutzen, um den Unterschied zwischen Arrays mit benutzerdefinierten Vergleichsfunktionen zu berechnen.

array_udiff_uassoc() berechnet den Unterschied zwischen zwei oder mehr Arrays und prüft dabei sowohl Schlüssel als auch Werte — und Sie bestimmen selbst, wie beides verglichen wird, indem Sie zwei eigene Callbacks angeben. Ein Element aus dem ersten array wird im Ergebnis nur dann beibehalten, wenn kein anderes array ein Element enthält, das sowohl beim Schlüssel als auch beim Wert übereinstimmt, gemäß Ihren Callbacks.

Diese Seite erklärt genau, wie die zwei Callbacks zusammenwirken (der Teil, den die meisten Referenz-Dokumentationen übergehen), führt durch ein ausführbares Beispiel und zeigt, wann diese Funktion das richtige Werkzeug ist im Vergleich zu ihren einfacheren Verwandten.

Was ist array_udiff_uassoc?

array_udiff_uassoc() gibt die Einträge von $array1 zurück, die in keinem der anderen Arrays vorhanden sind. Anders als array_diff(), das Werte nur per String-Casting vergleicht, prüft diese Variante Schlüssel und Werte gemeinsam und delegiert beide Vergleiche an benutzerdefinierte Funktionen — das ist die Bedeutung der zwei us im Namen (udiff = benutzerdefinierter Wertevergleich, uassoc = benutzerdefinierter Schlüsselvergleich).

Die Signatur lautet:

PHP array_udiff_uassoc Funktionssyntax

array_udiff_uassoc(
    array $array1,
    array $array2,
    array ...$arrays,        // one or more additional arrays
    callable $value_compare_func,
    callable $key_compare_func
): array

Die zwei Callbacks sind immer die letzten zwei Argumente, in dieser Reihenfolge: zuerst der Wertevergleich, dann der Schlüsselvergleich. Alles davor sind Arrays. Das Ergebnis ist ein neues array der Einträge aus $array1, die den Vergleich überleben, mit ihren ursprünglichen Schlüsseln.

Wie das Matching tatsächlich funktioniert. Für jeden Eintrag in $array1 durchsucht PHP die anderen Arrays nach einem Eintrag, dessen Schlüssel gemäß $key_compare_func „gleich" ist und dessen Wert gemäß $value_compare_func „gleich" ist. Existiert eine solche Übereinstimmung in einem anderen array, wird der Eintrag verworfen; andernfalls wird er beibehalten. Ein Eintrag wird nur entfernt, wenn beide Vergleiche Gleichheit melden.

Die Vergleichsfunktionen verstehen

Jeder Callback erhält zwei Argumente und muss einen Integer zurückgeben, genau wie ein Sortierkomparator:

  • Gibt 0 zurück, wenn die zwei Elemente als gleich betrachtet werden.
  • Gibt einen positiven Integer zurück, wenn das erste „größer" ist.
  • Gibt einen negativen Integer zurück, wenn das erste „kleiner" ist.

PHP interessiert sich nur dafür, ob der Rückgabewert 0 (gleich) ist oder nicht, aber ein konsistentes Drei-Wege-Ergebnis ist erforderlich, da die Funktion intern sortiert. Der Spaceship-Operator <=> ist der einfachste Weg, einen solchen Komparator zu schreiben:

$value_compare_func = fn($a, $b) => $a <=> $b;   // strict ordering
$key_compare_func   = fn($a, $b) => strcasecmp((string) $a, (string) $b); // case-insensitive keys

Da Sie beide Vergleiche definieren, können Sie Dinge tun, die die eingebauten Diff-Funktionen nicht können — zum Beispiel Schlüssel ohne Berücksichtigung der Groß-/Kleinschreibung behandeln oder Objekte anhand einer einzigen Eigenschaft vergleichen.

Beispiel: Grundlegende Verwendung

<?php

function compare_values($a, $b) {
    if ($a === $b) {
        return 0;
    }
    return ($a > $b) ? 1 : -1;
}

function compare_keys($a, $b) {
    if ($a === $b) {
        return 0;
    }
    return ($a > $b) ? 1 : -1;
}

$array1 = array('a' => 'apple', 'b' => 'banana', 'c' => 'cherry', 'd' => 'durian');
$array2 = array('a' => 'apple', 'b' => 'game', 'c' => 'cherry');
$array3 = array('a' => 'apple', 'b' => 'door', 'c' => 'cherry', 'g' => 'durian');

$result = array_udiff_uassoc($array1, $array2, $array3,  'compare_values', 'compare_keys');

print_r($result);

?>

Hier sind compare_values und compare_keys einfache Drei-Wege-Komparatoren. Der Aufruf vergleicht $array1 mit $array2 und $array3 und behält nur Einträge, deren Schlüssel und Wert nirgendwo anders übereinstimmen. Die Ausgabe lautet:

Array
(
    [b] => banana
    [d] => durian
)

Nachvollziehen, warum jeder Eintrag erhalten bleibt oder verworfen wird:

  • a => apple — verworfen: $array2 (und $array3) hat denselben Schlüssel a und denselben Wert apple.
  • b => bananabeibehalten: die anderen Arrays verwenden den Schlüssel b, aber ihre Werte sind game / door, nicht banana. Die Werte unterscheiden sich, daher gibt es keine Übereinstimmung.
  • c => cherry — verworfen: von beiden anderen Arrays gefunden.
  • d => durianbeibehalten: $array3 enthält den Wert durian, aber unter dem Schlüssel g, nicht d. Die Schlüssel unterscheiden sich, daher gibt es keine Übereinstimmung.

Dieser letzte Fall ist der eigentliche Zweck der Funktion: Obwohl der Wert durian anderswo existiert, stimmt der Schlüssel nicht überein, sodass der Eintrag erhalten bleibt. Ein reiner Wertevergleich wie array_udiff() hätte ihn entfernt.

Beispiel: Groß-/Kleinschreibung bei Schlüsseln ignorieren

Da Sie den Schlüsselvergleich selbst definieren, können Sie die Groß-/Kleinschreibung von Schlüsseln ignorieren und Werte trotzdem strikt vergleichen:

<?php

$wanted  = ['x' => 10, 'y' => 20, 'z' => 30];
$current = ['x' => 10, 'Y' => 20, 'z' => 99];

$result = array_udiff_uassoc(
    $wanted,
    $current,
    fn($v1, $v2) => $v1 <=> $v2,                       // values: strict ordering
    fn($k1, $k2) => strcasecmp((string) $k1, (string) $k2) // keys: case-insensitive
);

print_r($result);

Ausgabe:

Array
(
    [z] => 30
)

x => 10 und y => 20 werden entfernt (current hat denselben Wert unter einem Schlüssel, der ohne Berücksichtigung der Groß-/Kleinschreibung übereinstimmt), während z => 30 erhalten bleibt, weil current z => 99 enthält — der Schlüssel stimmt überein, aber der Wert 99 !== 30.

Wann verwenden (und was stattdessen nutzen)

Greifen Sie auf array_udiff_uassoc() nur zurück, wenn Sie benutzerdefinierte Logik für beides — Schlüssel und Werte — benötigen. Wenn Sie weniger benötigen, ist eine einfachere Variante schneller zu lesen und zu schreiben:

Sie müssen kontrollieren…Verwenden Sie
Nur Werte (Callback), Schlüssel ignoriertarray_udiff()
Werte (Callback) + Schlüssel mit ===array_udiff_assoc()
Schlüssel (Callback) + Werte mit ===array_diff_uassoc()
Keines — einfacher Wertevergleicharray_diff()

Häufige Fallstricke

  • Reihenfolge der Argumente. Die Callbacks sind die letzten zwei Argumente, Wertevergleich zuerst. Werden sie in der falschen Reihenfolge übergeben, produziert dies stillschweigend falsche Ergebnisse statt eines Fehlers.
  • Mindestens zwei Arrays. Sie müssen $array1, mindestens ein weiteres array und dann beide Callbacks übergeben — mindestens fünf Argumente.
  • Einen int zurückgeben, kein bool. Die Rückgabe von true/false aus einem Komparator funktioniert zufällig (sie werden zu 1/0 gecastet), bricht aber die Reihenfolge. Verwenden Sie <=> oder explizites -1/0/1.
  • Schlüssel bleiben erhalten. Das Ergebnis behält die ursprünglichen Schlüssel von $array1; es wird nicht neu indiziert.

Wenn Callbacks neu für Sie sind, lesen Sie PHP Callback Functions, und für eine Auffrischung zu Arrays im Allgemeinen PHP Arrays.

Fazit

array_udiff_uassoc() ist die flexibelste der PHP-Array-Differenzfunktionen: Sie vergleicht Einträge sowohl nach Schlüssel als auch nach Wert und überlässt beide Vergleiche Ihren eigenen Callbacks. Ein Eintrag aus dem ersten array überlebt nur, wenn kein anderes array ihn in beiden Dimensionen trifft. Verwenden Sie diese Funktion, wenn die eingebauten Vergleichsregeln (===, String-Casting) nicht ausreichen — zum Beispiel bei schlüsseln ohne Berücksichtigung der Groß-/Kleinschreibung, lokalebewussten Werten oder dem Vergleich von Objekten nach einem Feld — und greifen Sie auf eine einfachere array_diff*-Variante zurück, wenn Sie nicht so viel Kontrolle benötigen.

Übungen

Übung
Was ist die Funktionalität der array_udiff_uassoc-Funktion in PHP?
Was ist die Funktionalität der array_udiff_uassoc-Funktion in PHP?
Was this page helpful?