在JavaScript中展开一个数组的数组以获取最长的字符串

4
我将尝试将一个嵌套数组展平,并返回最长的字符串。
例如,给定以下输入:
i = ['big',[0,1,2,3,4],'tiny'] 

该函数应返回'tiny'。我想使用reduceconcat以一种本地且优雅的方式解决此问题(而不实现数组中的flatten原型),但我在这段代码中失败了:
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; 
        });
}

10
我认为你在压力下无法编写 JavaScript 代码... - Pointy
为什么不直接使用递归而不是将数组展平? - n.st
@Poinly 是的,我在第四关失败了 :) - shakaran
@n.st 我尝试使用递归来解决这个问题,它起作用了,但之前我无法理解这个缩减/联系的解决方案,所以我认为有人可以帮助我。 - shakaran
我刚刚注意到这个任务实际上不需要你递归进入任何子数组。 - n.st
2个回答

7

您遇到的问题是忘记向reduce函数传递initialValue参数,而在此情况下必须是一个数组。

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

如果不提供initialValue,第一次调用的a值将是i数组中的第一个元素,即在您的情况下是字符串big,因此您将调用String.prototype.concat函数而不是Array.prototype.concat函数。这意味着最后,r是一个字符串,而字符串没有reduce函数。但是,您的解决方案可以简化。
['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;
}, '');

哦!就是这样!我认为你现在赢得了被接受的答案,但其他提出的答案也非常好。 - shakaran
@shakaran 我更新了答案,提供了另一种解决方案。 - plalx
@shakaran,我已经删除了我的回答,plalx提供的代码更好。而且他也回答了你的问题。 - Jon Koops
@JonKoops,你的解决方案还是很不错的。使用Array.prototype.concat.apply来展开数组非常优雅。 - plalx
@plalx 是的,但不幸的是它不能展开一个超过2维的数组(虽然这不在问题中但仍很重要)。我喜欢你给函数命名并将其作为参数传递的方式,我会记住这个方法的。 - Jon Koops

0

你没有提到是否有多个具有相同长度的字符串 - 或者你是否关心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
*/

方法2:

您没有将字符串定义为单词-

任何数组分隔符都可以包含在任何值中,从而使我的解决方案不正确。

将数组展平使比较每个项的长度变得简单-

并且它不必作为原型方法完成:

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
*/

哦,我不知道IE8及以下版本没有reduce支持。你的解决方案对于缺少concat和reduce支持也非常好。也许这比使用reduce或concat的本地解决方案更具性能优势? - shakaran
2
@shakaran 不要因为不支持原生特性的旧浏览器而犹豫使用它们,只需使用像 https://github.com/kriskowal/es5-shim 这样的 shim 即可。 - plalx
@plalx 很好,非常有用的库! - shakaran

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接