Count Unique Values Across Nested Arrays In Ruby Without Duplicates
Tags across a set of posts, permissions across a set of roles, skills across a team — the data arrives as an array of arrays and you need the distinct total, or the frequency of each value across all the inner collections.
Description
flatten collapses the nesting, then uniq.size gives the distinct count. flat_map does the flatten and the extraction in one pass when the inner arrays need to be reached through a key or a method.
For frequency rather than a plain count, tally returns a hash of value to occurrence count in a single pass — faster and clearer than group_by plus transform_values.
Counting distinct containers per value — how many posts use each tag — needs uniq on the inner array first, or a post tagged “ruby” twice counts twice.
Sample input:
posts = [
{ title: "A", tags: ["ruby", "rails", "ruby"] },
{ title: "B", tags: ["rails", "hotwire"] },
{ title: "C", tags: ["ruby"] }
]
Sample Output:
# distinct tags => 3
# frequency => { "ruby" => 2, "rails" => 2, "hotwire" => 1 }
Answer
nested = [["ruby", "rails"], ["rails", "hotwire"], ["ruby"]]
nested.flatten.uniq.size
# => 3
nested.flatten.uniq
# => ["ruby", "rails", "hotwire"]
# Reach into a key — one pass
posts.flat_map { |p| p[:tags] }.uniq.size
# => 3
# Frequency across everything, duplicates within a post included
posts.flat_map { |p| p[:tags] }.tally
# => { "ruby" => 3, "rails" => 2, "hotwire" => 1 }
# How many POSTS use each tag — dedupe within each post first
posts.flat_map { |p| p[:tags].uniq }.tally
# => { "ruby" => 2, "rails" => 2, "hotwire" => 1 }
# Only values appearing in more than one post
posts.flat_map { |p| p[:tags].uniq }
.tally
.select { |_, count| count > 1 }
.keys
# => ["ruby", "rails"]
# Arbitrary nesting depth
[[1, [2, 3]], [3, [4]]].flatten.uniq.size # => 4
# Large collections — Set avoids building the intermediate array
require "set"
posts.each_with_object(Set.new) { |p, set| set.merge(p[:tags]) }.size
Check viewARU - Brand Newsletter!
Newsletter to DEVs by DEVs - boost your Personal Brand & career! 🚀