How to find longest string value in JavaScript array
Finding a longest string in JavaScript array is a useful operation to determine needed space for displaying data. In this article, we fill analyse all possible solutions and compare them by readability, speed and memory. For example, I do this constantly in my charts library to allocate a space for y/x axes ticks.
Task overview
Given an array of values, find the longest (string) value in array.
Array given: [1, 10, 'longest string', false, ['this', 'may', 'be', 'long', 'enough;], { prop: 'value' }, 'short string', null, undefined]
.
Expected output: longest string
.
Theory
MDN Object.prototype.toString()
documentation.
There are two ways of converting any entity to string. Let’s explore them.
“Everything in JavaScript is an object”
Well, actually, not.
There are 7 primitives: String
, Number
, BigInt
, Boolean
, undefined
, null
, Symbol
. Every primitive is not an object, although every primitive have object wrappers. We can’t convert non-primitive entities to, say, real string, meaning values that we, humans, can treat as strings.
Which data to consider possible to convert to strings
I would say that such tasks may need an extra details to consider, but for given task let’s say that we only want to compare primitives. But since null
or undefined
mean that variable have no value, we will only consider String
, Number
, BigInt
and Boolean
values. Every Symbol
is unique and is not countable, so we will not consider these values too (more on Symbol
primitive here).
All primitives that we consider as “real” strings have own toString()
method that gives an interpretation of value as a string.
How to convert to a string?
Calling toString()
method
Simple as that. Just call variable.toString()
and get a string representation.
Calling String()
constructor
Write String(variable)
and get the string representation. Using String
constructor like this is roughly the same as calling toString()
method. At least, on choosen primitives.
String concatenation via +
assignment operator
Although there is String.prorotype.concat()
method, MDN docs says to use +
or +=
operators to concat strings because of performance reasons (seems like they removed the section, you can see corresponding article on web.archive.org).
Calling '' + variable
will give the same result as calling ''.concat(variable)
which converts variable to String
and then concats it with empty string.
Iterating over array
There are 5 ways to iterate over array:
Let’s try them and see how they perform.
Finding the longest (string) value in array
For our operations we will consider:
const arr = [1, 10, 'longest string', false, ['this', 'may', 'be', 'long', 'enough;], { prop: 'value' }, 'short string', null, undefined];
const arrLength = arr.length;
const primitives = [ 'string', 'number', 'bigint', 'boolean' ];
let longestLength = 0;
let longestValue = null;
for
loop
for (let i = 0; i < arrLength; i++) {
const value = arr[i];
if (primitives.includes(typeof value)) {
const valueLength = value.toString().length;
if (valueLength > longestLength) {
longestLength = valueLength;
longestValue = value;
}
}
}
for _ of
loop
for (const value of arr) {
if (primitives.includes(typeof value)) {
const valueLength = value.toString().length;
if (valueLength > longestLength) {
longestLength = valueLength;
longestValue = value;
}
}
}
foreach()
method
arr.forEach(value => {
if (primitives.includes(typeof value)) {
const valueLength = value.toString().length;
if (valueLength > longestLength) {
longestLength = valueLength;
longestValue = value;
}
}
});
map()
method
arr.map(value => {
if (primitives.includes(typeof value)) {
const valueLength = value.toString().length;
if (valueLength > longestLength) {
longestLength = valueLength;
longestValue = value;
}
}
});
reduce()
method
arr.reduce((previousValue, currentValue) => {
if (primitives.includes(typeof currentValue)) {
const valueLength = currentValue.toString().length;
if (valueLength > longestLength) {
longestLength = valueLength;
previousValue = currentValue;
}
}
}, longestLength);
Analysis
As we can see, all loops basically performing same operation under the condition. Also, just by looking at the code, it is clear, that last 2 methods ( map()
and reduce()
) are overhead. But we will consider them in our tests anyways.
Performance
Let’s head to https://jsben.ch/ and create some tests.
1k entries
As expected, simple for
loop performing better than other methods, with map
being the slowets.
Benchmark available here: https://jsben.ch/APBhX.
1M entries
For this test case for
loop is still the best choice with reduce
and forEach
methods tieing second place.
Benchmark available here: https://jsben.ch/Cu9H2.
Conclusion
In the given case using simple and robust for
loop being the best choice, as the readability of code stays the same as with other methods, but the speed being fastest.