Enumerable#uniq
6th day of Enumerable week and it's time for Enumerable#uniq.
Not too much to say about this one, to be honest. It does what it says on the tin: removes duplicate values from the collection. What actually feels remarkable is that so few other languages have this as a built-in method, considering how common the operation is.
In other languages the approach is often to convert collections to a Set or similar data structure instead. But there is something about uniq which just feels right. I guess it's the human aspect of it - anyone can understand "give me the unique elements from this collection". Comprehending what a "set" is, on the other hand, requires a mathematical background.
numbers = [1, 2, 2, 3, 4, 4, 4, 5]
unique_numbers = numbers.uniq
# => [1, 2, 3, 4, 5]
fruits = ["apple", "banana", "apple", "cherry", "banana"]
unique_fruits = fruits.uniq
# => ["apple", "banana", "cherry"]
const numbers = [1, 2, 2, 3, 4, 4, 4, 5];
const uniqueNumbers = [...new Set(numbers)];
// => [1, 2, 3, 4, 5]
const fruits = ["apple", "banana", "apple", "cherry", "banana"];
const uniqueFruits = [...new Set(fruits)];
// => ["apple", "banana", "cherry"]
You can also provide a block to uniq to customize how uniqueness is determined.
people = [
{ name: "Alice", age: 30 },
{ name: "Bob", age: 25 },
{ name: "Charlie", age: 30 },
]
unique_by_age = people.uniq { |person| person[:age] }
# => [{ name: "Alice", age: 30 }, { name: "Bob", age: 25 }]
const people = [
{ name: "Alice", age: 30 },
{ name: "Bob", age: 25 },
{ name: "Charlie", age: 30 },
];
const uniqueByAge = Array.from(
new Map(people.map(person => [person.age, person])).values()
);
// => [{ name: "Charlie", age: 30 }, { name: "Bob", age: 25 }]
There is also a "banged" version, uniq!, which mutates the original collection in place. Useful if you're memory-conscious and don't need to reference the original collection anymore.
Oh, and if you really do want a Set, you can just invoke to_set instead.
History
The method was originally only available on Array and was implemented at the latest in Ruby 1.4 all the way back in the late 90s. It wasn't until Ruby 2.4 in 2016 that it was added to Enumerable.
But let's address the elephant in the room: why is it called uniq and not unique?
It's probably another example of Ruby's roots as an "object-oriented UNIX". Unix had a command-line tool called uniq from its very early days, used to remove duplicate lines from text files.
Enjoy keeping your collections tidy with uniq!