Arrays7 min readExamples run on PHP 8.5.10

array_udiff_uassoc()

Learn how array_udiff_uassoc() finds entries in one array that no other array matches by both value and key, using two callbacks you supply.

Signature

array_udiff_uassoc(
    array $array,
    array ...$arrays,
    callable $value_compare_func,
    callable $key_compare_func
): array

Purpose

array_udiff_uassoc() returns the entries of the first array that have no match in any of the other arrays. An entry only counts as a match when both its value and its key are considered equal. Unlike array_diff_assoc(), you decide what "equal" means for both parts: one callback compares values and a second callback compares keys.

Use it when plain ===-style comparison is too strict, for example when keys differ only by case, or when values are records that should be matched by an identifier.

Signature

Parameters

  • $array: the array whose entries are tested. Its keys are preserved in the result.
  • ...$arrays: one or more arrays to compare against.
  • $value_compare_func: receives two values and returns an integer that is negative, zero or positive. Zero means the values are equal.
  • $key_compare_func: receives two keys and follows the same contract. Zero means the keys are equal.

The two callbacks are always the last two arguments, in that order. There are no default values; all parts are required apart from the extra comparison arrays.

Return value and failures

The function returns an array with every entry from $array that is not matched in any other array. If everything is matched, the result is an empty array. The input arrays are never modified.

Passing something that is not an array or not a callable where one is required results in a TypeError. Exceptions thrown inside a callback propagate to your code.

Example 1: case-insensitive values and keys

Here both callbacks are strcasecmp, so 'a' and 'A' are the same key, and 'Apple' and 'apple' are the same value.

Example
<?php
$a = ['a' => 'Apple', 'b' => 'Banana', 'c' => 'Cherry'];
$b = ['A' => 'apple', 'b' => 'Blueberry', 'd' => 'cherry'];

$result = array_udiff_uassoc($a, $b, 'strcasecmp', 'strcasecmp');

echo json_encode($result, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES), "\n";
Output
{"b":"Banana","c":"Cherry"}

Apple is removed because both key and value match. Banana stays because its key matches but its value does not. Cherry stays because no key in $b equals c, even though the value matches d.

Example 2: matching records by id against several arrays

When values are arrays, the value callback can compare just the field that identifies a record. With several comparison arrays, an entry is dropped if any one of them matches it.

Example
<?php
$current = [
    10 => ['id' => 1, 'name' => 'Ana'],
    11 => ['id' => 2, 'name' => 'Ben'],
    12 => ['id' => 3, 'name' => 'Cy'],
];
$archived = [
    10 => ['id' => 1, 'name' => 'Old Ana'],
    12 => ['id' => 9, 'name' => 'Other'],
];
$blocked = [
    11 => ['id' => 2, 'name' => 'Blocked'],
];

$result = array_udiff_uassoc(
    $current,
    $archived,
    $blocked,
    fn(array $x, array $y): int => $x['id'] <=> $y['id'],
    fn(int $x, int $y): int => $x <=> $y
);

echo json_encode($result, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES), "\n";
Output
{"12":{"id":3,"name":"Cy"}}

Key 10 matches in $archived, key 11 matches in $blocked, but key 12 has different ids, so only that entry survives.

Example 3: absolute values and case-insensitive keys

Example
<?php
$a = ['Mon' => 5, 'Tue' => -3, 'Wed' => 8];
$b = ['mon' => -5, 'tue' => 3, 'WED' => 7];

$result = array_udiff_uassoc(
    $a,
    $b,
    fn(int $x, int $y): int => abs($x) <=> abs($y),
    'strcasecmp'
);

echo json_encode($result, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES), "\n";
Output
{"Wed":8}

Only Wed remains, because 8 and 7 have different absolute values.

Edge cases

  • Keys are preserved. The result keeps the original keys from the first array; nothing is renumbered.
  • Only the first array contributes entries. Entries that exist only in later arrays never appear in the result.
  • Callbacks must be consistent. Each array is sorted internally before comparison, so a callback may receive any value from any array in any order. It must give a coherent ordering for everything it can see.
  • Only one dimension is checked. Nested arrays are not compared recursively unless your callback does that work.
  • Mixed types. If arrays hold different kinds of values, your callback must handle every combination.

Common mistakes

  1. Returning a boolean or float. The callbacks must return an integer. A float such as 0.5 is cast to 0 and reads as "equal". A boolean from == gives true (1) for equal values, which is the opposite of what you want. Use the spaceship operator <=> or strcmp-style functions.
  2. Swapping the callbacks. The value callback comes first and the key callback second. Reversing them compares keys with your value logic.
  3. Expecting key-only or value-only matching. Both must match for an entry to be removed. If you need only values, use array_udiff(); if keys use the built-in comparison, use array_udiff_assoc().
  4. Writing an order-dependent callback. A callback that assumes the first argument always comes from the first array can produce wrong results.
  5. Assuming deep comparison. For nested data, compare the relevant inner field explicitly.
  • array_diff() and array_diff_assoc() for built-in comparisons
  • array_udiff() for a custom value callback only
  • array_udiff_assoc() for a custom value callback and built-in key comparison
  • array_diff_uassoc() for built-in value comparison and a custom key callback
  • array_uintersect_uassoc() for the intersection counterpart

Recap

array_udiff_uassoc() keeps the entries of the first array whose value and key pair is not matched in any other array, using two integer-returning callbacks you provide: values first, keys second. Keep the callbacks consistent, return real integers, and remember that keys are preserved.

Tested examples

Case-insensitive values and keys
<?php
$a = ['a' => 'Apple', 'b' => 'Banana', 'c' => 'Cherry'];
$b = ['A' => 'apple', 'b' => 'Blueberry', 'd' => 'cherry'];

$result = array_udiff_uassoc($a, $b, 'strcasecmp', 'strcasecmp');

echo json_encode($result, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES), "\n";
Output
{"b":"Banana","c":"Cherry"}
Matching records by id against several arrays
<?php
$current = [
    10 => ['id' => 1, 'name' => 'Ana'],
    11 => ['id' => 2, 'name' => 'Ben'],
    12 => ['id' => 3, 'name' => 'Cy'],
];
$archived = [
    10 => ['id' => 1, 'name' => 'Old Ana'],
    12 => ['id' => 9, 'name' => 'Other'],
];
$blocked = [
    11 => ['id' => 2, 'name' => 'Blocked'],
];

$result = array_udiff_uassoc(
    $current,
    $archived,
    $blocked,
    fn(array $x, array $y): int => $x['id'] <=> $y['id'],
    fn(int $x, int $y): int => $x <=> $y
);

echo json_encode($result, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES), "\n";
Output
{"12":{"id":3,"name":"Cy"}}
Absolute values and case-insensitive keys
<?php
$a = ['Mon' => 5, 'Tue' => -3, 'Wed' => 8];
$b = ['mon' => -5, 'tue' => 3, 'WED' => 7];

$result = array_udiff_uassoc(
    $a,
    $b,
    fn(int $x, int $y): int => abs($x) <=> abs($y),
    'strcasecmp'
);

echo json_encode($result, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES), "\n";
Output
{"Wed":8}