How Lodash _.xor Computes Array Symmetric Difference

The _.xor method in the Lodash JavaScript library calculates the symmetric difference across multiple arrays by returning a new array of unique values that appear in only one of the provided arrays. Unlike standard set operations that are limited to pairs of sets, Lodash generalizes symmetric difference to multiple inputs by filtering out any element that appears in two or more arrays. This article examines the behavior of _.xor, explains its internal algorithm using Lodash's core operations, and demonstrates how it processes both two-array and multi-array inputs.

What is Symmetric Difference in Lodash?

In mathematical set theory, the symmetric difference of two sets \(A\) and \(B\) consists of elements that belong to either \(A\) or \(B\), but not both (\(A \Delta B = (A \setminus B) \cup (B \setminus A)\)).

When working with more than two sets, symmetric difference can mathematically be interpreted in two ways:

  1. Parity-based: Elements present in an odd number of sets.
  2. Exclusivity-based: Elements present in exactly one set.

Lodash adopts the exclusivity-based approach. When _.xor is supplied with two or more arrays, it creates an array of unique values that exist in exactly one of the given arrays, excluding any element that occurs in multiple arrays.

Basic Syntax and Usage

import _ from 'lodash';

const array1 = [2, 1];
const array2 = [2, 3];

const result = _.xor(array1, array2);
console.log(result);
// => [1, 3]

In this two-array example:

How the Algorithm Works Internally

Under the hood, Lodash executes _.xor using internal utility functions including baseXor, baseDifference, baseFlatten, and baseUniq. The computation proceeds through the following steps:

1. Handling Edge Cases

If no arrays are provided, _.xor returns an empty array []. If only one array is passed, Lodash passes it through baseUniq to strip duplicate values and returns the result.

2. Relative Difference Across All Other Arrays

When two or more arrays are passed, Lodash iterates through each array in the arguments list. For each array at index i, Lodash calculates its difference relative to every other array at index j (where i !== j) using baseDifference:

\[\text{exclusive}_i = \text{array}_i \setminus \bigcup_{j \neq i} \text{array}_j\]

Any item in array_i that is also found in another array is eliminated.

3. Flattening and Deduplication

Once each array has been stripped of elements shared with other arrays:

  1. The remaining exclusive arrays are flattened into a single list using a shallow flatten operation (baseFlatten).
  2. The flattened list is passed through baseUniq to ensure that duplicate values within the same source array appear only once in the final output.
  3. The resulting array preserves the relative order of elements based on their original appearance across the input arrays.

Multi-Array Example

The distinction of Lodash's exclusivity rule becomes apparent when working with three or more arrays:

const a = [1, 2];
const b = [2, 3];
const c = [1, 4];

console.log(_.xor(a, b, c));
// => [3, 4]

Tracing the execution:

The final result is [3, 4].

Comparison with _.xorBy and _.xorWith

Lodash also provides custom-comparator variants of the symmetric difference algorithm:

Both variants follow the same algorithmic structure as _.xor, but replace the default strict equality checks (===) inside baseDifference and baseUniq with the user-defined iteratee or comparator.