# delete occurrences of extra elements in an array

Create a function that takes two arguments: an array `arr` and a number `num`. If an element occurs in `arr` more than `num` times, remove the extra occurrence(s) and return the result.

``````deleteOccurrences([1, 1, 1, 1], 2) ➞ [1, 1]
deleteOccurrences([13, true, 13, null], 1) ➞ [13, true, null]
deleteOccurrences([true, true, true], 3) ➞ [true, true, true]``````

Two solutions:

1. Initialize a new array. For each element, we check if the array already contains `i` number of elements. If it does, we do nothing. If not, we append it to the array.
2. Deduplicate the original array, map over it and somehow find a way to repeat the elements `i` times, flattening it when we’re done.

Crystal:

``````def delete_occurrences(arr : Array(T), i : Int32) forall T
res = [] of T
arr.each { |el| res << el if res.count(el) < i }
res
end

def delete_occurrences_func(arr : Array(T), i : Int32) forall T
arr.uniq.flat_map { |el| Array.new(i, el) }
end``````

Nim:

``````func deleteOccurrences[T](s: seq[T], i: int): seq[T] =
for el in s:
if result.count(el) == i: continue

func deleteOccurrencesFunc[T](s: seq[T], i: int): seq[T] =
let newS = collect(newSeq):
for el in s.deduplicate:
el.repeat(i)
return newS.foldl(a & b)``````

Found another use for `collect`, which I’ve been using a lot more in recent days.

Raku:

``````sub delete-occurrences(@a, \$i) {
my @n = [];
for @a -> \$el {
@n.push(\$el) if @n.grep({\$_ eqv \$el}).elems < \$i;
}
@n;
}

sub delete-occurrences-func(@a, \$i) {
(do for @a.unique {\$_ xx \$i}.flat).Array;
}

ok delete-occurrences([13, True, 13, True], 1) == [13, True];``````

A gotcha: we cannot use smartmatching for the first solution when grepping! Any value that is truthy will evaluate to true, and that means we get a lot more elements than we want! Instead, we check that `\$_` is strictly `eqv` to `\$el`.

Javascript:

``````function deleteOccurrences<T>(a: T[], i: number) {
const newA = [];
const map: Map<T, number> = new Map();

for (const el of a) {
const count = map.get(el) || 0;
if (count !== i) {
map.set(el, count + 1);
newA.push(el);
}
}

return newA;
}

function deleteOccurrencesFunc<T>(a: T[], i: number) {
const newA = [...new Set(a)];
return newA.flatMap((el) => new Array(i).fill(el));
}``````

Ugh… that first implementation is a lot longer than I would like. I don’t get why we don’t have `count` yet in Javascript.

Built with Astro and Tailwind 🚀