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:

  1. for loop MDN
  2. for _ of loop MDN
  3. foreach() method MDN
  4. map() method MDN
  5. reduce() method MDN

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.

1000 entries test result

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.

1000000 entries test result

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.

$ cd ..