Array#difference
What does Array#difference do?
Array#difference returns a new array containing the elements that are present in self but not in the given arrays. It performs a set-style comparison — each element is checked for presence in the argument arrays, and all matching occurrences are excluded.
Basic usage
a = [1, 2, 3, 4, 5]
b = [2, 4]
a.difference(b)
# => [1, 3, 5]
The original array a is not modified:
a = [1, 2, 3, 4, 5]
b = [2, 4]
a.difference(b)
# => [1, 3, 5]
a
# => [1, 2, 3, 4, 5]
Removing all occurrences
Note that difference removes all occurrences of each element found in the argument arrays:
a = [1, 2, 2, 2, 3, 4, 2]
b = [2]
a.difference(b)
# => [1, 3, 4]
Every 2 in a is removed, not just one.
Difference with multiple arrays
You can pass multiple arrays to difference. It removes elements present in any of them:
a = [1, 2, 3, 4, 5, 6]
b = [2, 4]
c = [5]
a.difference(b, c)
# => [1, 3, 6]
difference vs the - operator
Array#difference and Array#- are functionally identical. - is the traditional operator:
a = [1, 2, 3, 4, 5]
b = [2, 4]
a - b
# => [1, 3, 5]
a.difference(b)
# => [1, 3, 5]
Use whichever you prefer. - reads more naturally in expressions; #difference reads as a method call and can be chained.
difference vs delete_if
delete_if removes elements based on a condition, while difference removes based on set membership:
# delete_if removes conditionally
a = [1, 2, 3, 4, 5]
a.delete_if { |x| x.even? }
# => [1, 3, 5]
# difference removes by set comparison
a = [1, 2, 3, 4, 5]
b = [2, 4]
a.difference(b)
# => [1, 3, 5]
delete_if evaluates a block for each element. difference checks membership in another array without a block.
Practical examples
Removing excluded categories
available = ["ruby", "python", "javascript", "go", "rust"]
excluded = ["python", "go"]
available.difference(excluded)
# => ["ruby", "javascript", "rust"]
Filtering out blocked users
all_users = ["alice", "bob", "charlie", "diana", "eve"]
blocked = ["bob", "diana"]
all_users.difference(blocked)
# => ["alice", "charlie", "eve"]
Removing admin roles from a permission list
all_roles = ["read", "write", "delete", "admin", "superadmin"]
elevated = ["admin", "superadmin"]
all_roles.difference(elevated)
# => ["read", "write", "delete"]
Performance notes
Array#difference has a time complexity of O(n), where n is the length of self. It builds a set from the argument arrays for O(1) lookup, then iterates through self once.
For large arrays or frequent calls, consider whether the argument arrays are large — if both arrays are large, the operation can become expensive. In such cases, a Set may offer better performance depending on your use case.
See Also
- /reference/array-methods/array-intersection/ — returns elements common to both arrays
- /reference/array-methods/array-reject/ — removes elements matching a condition
- /reference/enumerable/include/ — checks if an array contains a specific element