Question

I am trying to flatten an array of arrays in a input, and return the longest string.

For example given the input:

i = ['big',[0,1,2,3,4],'tiny'] 

The function should return 'tiny'. I would like use reduce or concat for resolve this in a native and elegant way (without implement a flatten prototype in array) but I am failing with this code:

function longestStr(i) 
{
    // It will be an array like (['big',[0,1,2,3,4],'tiny'])
    // and the function should return the longest string in the array

    // This should flatten an array of arrays
    var r = i.reduce(function(a, b)
    {
         return a.concat(b);
    });

    // This should fetch the longest in the flattened array
    return r.reduce(function (a, b) 
        { 
            return a.length > b.length ? a : b; 
        });
}
Was it helpful?

Solution

Your issue is that you forgot to pass in the initialValue argument to the reduce function, which must be an array in this case.

var r = i.reduce(function(a, b) {
    return a.concat(b);
}, []);

Without providing an initialValue, the a value for the first call will be the first element in the i array, which is the string big in your case, so you will be calling the String.prototype.concat function instead of Array.prototype.concat.

That means at the end, r is a string and strings don't have a reduce function.

Your solution could be simplified however:

['big',[0,1,2,3],'tiny'].reduce(function longest(a, b) {
    b = Array.isArray(b)? b.reduce(longest, '') : b;
    return b.length > a.length? b : a;
}, '');

OTHER TIPS

You don't mention having multiple strings with the same length- or if you care about IE8...

function longestStr(A){
    var i= 0, len, A= String(A).split(/\b/).sort(function(a, b){
        return a.length<b.length;
    });
    len= A[0].length;
    while(A[i].length==len)++i;
    return A.slice(0, i);
}

var A1= ['big', [0, 1, 2, 3, 4], 'tiny',[1,2,3,'puny']];
longestStr(A1);

/*  returned value: (Array)
tiny,puny
*/

Method 2:

You did not define a string as a single word-

any array delimeters could be included in any of the values, making my solution incorrect.

Flattening the array makes comparing each item's length simple-

and it does not have to be done as a prototype method:

function longestStr(array){
    function flatten(arr){
        var A1= [], L= arr.length, next;
        for(var i= 0; i<L; i++){
            next= arr[i];
            if(next.constructor!= Array) A1.push(String(next));
            else A1= A1.concat(flatten(next));
        }
        return A1;
    }
    var i= 0, len, A=flatten(array);
    A.sort(function(a, b){
        return a.length<b.length;
    });
    len= A[0].length;
    while(A[i].length== len)++i;
    return A.slice(0, i);
}
var Ax= ['big stuff', [0, 1, 2, 3, 4], 'tiny', [1, 2, 3, 'puny']];
longestStr(Ax);

/*  returned value: (Array)
big stuff
*/
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top