Write code to find frequency of elements in an array
Reduce into a Map (or plain object): for each element, increment its count. `new Map` if keys may be objects or non-strings; object literal if all keys are strings/numbers (faster lookup, JSON-friendly). `Object.create(null)` to avoid prototype-chain key collisions like `__proto__`.
Common interview warm-up; also a real pattern for cardinality histograms.
Map version (keys can be anything)
function freq(arr) {
const m = new Map();
for (const x of arr) m.set(x, (m.get(x) ?? 0) + 1);
return m;
}
freq(["a", "b", "a", "c", "b", "a"]);
// Map { "a" => 3, "b" => 2, "c" => 1 }Map accepts any key (objects, NaN, etc.), preserves insertion order, and has O(1) get/set.
Object version (string/number keys)
function freq(arr) {
const out = Object.create(null);
for (const x of arr) out[x] = (out[x] ?? 0) + 1;
return out;
}Object.create(null) avoids inherited keys (so __proto__, constructor etc. are normal keys, not booby traps).
Reduce version
const freq = (arr) => arr.reduce((acc, x) => ((acc[x] = (acc[x] ?? 0) + 1), acc), Object.create(null));Compact, same shape.
Sorted by count
function topByFreq(arr, k) {
const m = freq(arr);
return [...m.entries()].sort((a, b) => b[1] - a[1]).slice(0, k);
}Bucket sort for top-k frequencies (O(n))
function topK(arr, k) {
const m = freq(arr);
const buckets = Array(arr.length + 1).fill(null).map(() => []);
for (const [v, c] of m) buckets[c].push(v);
const out = [];
for (let i = buckets.length - 1; i >= 0 && out.length < k; i--) {
for (const v of buckets[i]) {
out.push(v);
if (out.length === k) break;
}
}
return out;
}Linear-time top-k by frequency — better than sort for large n.
Edge cases
- Empty array → empty Map/object.
- NaN as a key → Map handles it; plain object coerces to
"NaN"string. null/undefined→ object coerces to"null"/"undefined"; Map keeps them distinct.- Object keys → only Map handles; plain object stringifies to
"[object Object]"for all → collisions. - Symbols → can't be keys in plain object lookup the same way.
Interview framing
"Reduce into a Map, incrementing per element — O(n), O(distinct) memory. Plain object is fine for string/number keys; use Object.create(null) to avoid prototype collisions. Map if keys can be objects or you need insertion order. For top-k by frequency without sorting, bucket sort by count is O(n). Edge cases: NaN, null, object keys — all only work cleanly with Map."
Follow-up questions
- •When to use Map vs object?
- •How would you find the top-k most frequent?
- •What's the time complexity?
Common mistakes
- •Using plain object with object keys.
- •Forgetting prototype-chain hazards (use Object.create(null)).
- •Re-traversing the array per element (O(n²)).
Performance considerations
- •Single pass O(n). Map.get/set is O(1) amortized. Bucket sort beats sort for top-k.
Edge cases
- •NaN, null, undefined keys.
- •Very large arrays — memory of the Map.
- •Symbol keys.
Real-world examples
- •Analytics distribution, word frequency, top tags, leaderboards.