Separation of concerns
The problem has two distinct, independent components:
- Compute run length
- Decide if two values are equal
I agree that using reduce
makes sense here to compute the run length. If you separate this computation from the equality decision, the logic of the reducer can become a lot simpler:
const reducer = (acc, val) => {
if (acc.length > 0 && equals(acc[acc.length - 1][1], val)) {
acc[acc.length - 1][0]++;
return acc;
}
acc.push([1, val]);
return acc;
};
return arr.reduce(reducer, []);
That is:
-
When the accumulator is not empty, and the last element has matching value, then increment the count of the last element, and return the accumulator.
-
Append
[1, val]
to the accumulator. -
The accumulator starts empty.
The equality condition is to be implemented. You can even require the implementation to be passed in as parameter.
As @radarbob suggests, it's good to get the run-length computation working without worrying about mixed value types. The implementation of the equals
function here is not interesting at all for run-length computation. You can start with a simple const equals = (a, b) => a === b
. Having mixed values in the input doesn't affect at all the run-length computation logic.
The converse is also true: it should be possible to implement the equality logic independently from run-length. This reduces your mental burden and helps you think clearly, focusing on one problem at a time. I came up with this:
const equals = (a, b) => {
if (a === b) {
return true;
}
if (typeof(a) !== typeof(b)) {
return false;
}
if (Array.isArray(a)) {
return arrayEquals([a, b]);
}
return false;
};
This implementation handles some easy basic cases, and delegates some non-trivial ones, such as comparing arrays. Your arrayEquals
will work nicely for the purpose. Looking at this implementation, it's also quite clear what kind of values are supported: primitive and arrays only. (As far as we can trust the externalized arrayEquals
implementation...)
manpreet
Best Answer
2 years ago
I have implemented a custom run length encoding algorithm that converts an m x n array into an p x (n+1) array. The extra column is to record counts. Probably easier to show through examples: