简体   繁体   中英

Find the longest string in a nested array using Recursion in Javascript?

I have seen various answers which give a solution to finding the longest string in an array. My problem is, I want to find the longest string in a nested array. The nesting level may be of N-levels or just two levels deep. My initial solution is as follows:

    let myArray = [
    'ABC',
    'ABCD',
    'ABCDE',
    [
      'ABC',
      'ABCABABA',
      [
        'ABABABABABABABABAZZ'
      ],
    'ABCABABASS',

     ],
   'ABCDEFGH',
   'ABABABABZZQ'
   ]

function longestString(arr) {
let longestStr = ''
arr.forEach(item => {
if(typeof item === 'string') {
  if(item.length > longestStr.length) {
    longestStr = item;
    console.log('Longest Item', item);
  }    
} else {
    longestString(item)
  }
})
 return longestStr;
}

console.log(longestString(myArray))

Observed Output -> ABABABABZZQ

Expected Output -> 'ABABABABABABABABAZZ'

What is the tweak needed to print only the longest string?

You need to use the return value of the recursive call - put the returned string through the same test that you put the item through, check if it's longer than longestStr , and if so, reassign longestStr :

 let myArray = [ 'ABC', 'ABCD', 'ABCDE', [ 'ABC', 'ABCABABA', [ 'ABABABABABABABABAZZ' ], 'ABCABABASS', ], 'ABCDEFGH', 'ABABABABZZQ' ] function longestString(arr) { let longestStr = '' arr.forEach(item => { if (typeof item === 'string') { if (item.length > longestStr.length) { longestStr = item; } } else { const nestedLongest = longestString(item); if (nestedLongest.length > longestStr.length) { longestStr = nestedLongest; } } }) return longestStr; } console.log(longestString(myArray)) 

Or, to be somewhat more DRY:

 const myArray=['ABC','ABCD','ABCDE',['ABC','ABCABABA',['ABABABABABABABABAZZ'],'ABCABABASS',],'ABCDEFGH','ABABABABZZQ'] function longestString(arr) { let longestStr = ''; const check = str => { if (str.length > longestStr.length) longestStr = str; }; arr.forEach(item => { check(typeof item === 'string' ? item : longestString(item)); }); return longestStr; } console.log(longestString(myArray)) 

Another option would be to have an inner function that gets called, while assigning to a longestStr variable that's persistently in scope until the end of the longestString function - meaning that you don't have to worry about the results of the recursive calls:

 const myArray=['ABC','ABCD','ABCDE',['ABC','ABCABABA',['ABABABABABABABABAZZ'],'ABCABABASS',],'ABCDEFGH','ABABABABZZQ'] function longestString(input) { let longestStr = ''; const check = str => { if (str.length > longestStr.length) longestStr = str; }; function recursiveFn(arr) { arr.forEach((item) => { if (typeof item === 'string') check(item) else recursiveFn(item); }); } recursiveFn(input); return longestStr; } console.log(longestString(myArray)) 

Use Array.flat() to flatten the array, and then use Array.reduce() to find the longest item:

 const myArray = [ 'ABC', 'ABCD', 'ABCDE', [ 'ABC', 'ABCABABA', [ 'ABABABABABABABABAZZ' ], 'ABCABABASS', ], 'ABCDEFGH', 'ABABABABZZQ' ] const result = myArray .flat(Infinity) .reduce((r, s) => s.length > r.length ? s : r); console.log(result); 

You have to declare longestStr outside the function and also you have to use the return keyword

return longestString(item)

 let myArray = [['ABC','ABCD','ABCDE', ['ABC','ABCABABA', ['ABABABABABABABABAZZ'], 'ABCABABASS'], 'ABCDEFGH', 'ABABABABZZQ']] let longestStr = '' function longestString(arr) { arr.forEach(item => { if(typeof item === 'string') { if(item.length > longestStr.length) { longestStr = item; console.log('Longest Item', item); } } else { return longestString(item) } }); return longestStr; } console.log(longestString(myArray)); 

EDIT - You can pass longestStr as parameter to longestString function

 let myArray = [['ABC','ABCD','ABCDE', ['ABC','ABCABABA', ['ABABABABABABABABAZZ'], 'ABCABABASS'], 'ABCDEFGH', 'ABABABABZZQ']] function longestString(arr,longestStr) { arr.forEach(item => { if(typeof item === 'string') { if(item.length > longestStr.length) { longestStr = item; console.log('Longest Item', item); } } else { var value = longestString(item,longestStr); if(value.length > longestStr.length){ longestStr = value; } return longestStr; } }); return longestStr; } console.log(longestString(myArray,'')); 

You can do it with a single reduce

 const myArray = [ 'ABC', 'ABCD', 'ABCDE', [ 'ABC', 'ABCABABA', [ 'ABABABABABABABABAZZ' ], 'ABCABABASS', ], 'ABCDEFGH', 'ABABABABZZQ' ]; const findLongestStr = array => array.reduce((result, item) => typeof item === 'string' ? item.length > result ? item : result : findLongestStr(item), ''); console.log(findLongestStr(myArray)); 

Recursively call the findLongestStr if the input is Array and maintain the current maximum value.

let myArray = [
    'ABC',
    'ABCD',
    'ABCDE',
    [
      'ABC',
      'ABCABABA',
      [
        'ABABABABABABABABAZZ'
      ],
    'ABCABABASS',

     ],
   'ABCDEFGH',
   'ABABABABZZQ'
   ];

function findLongestStr(input){
  return input.reduce(function(o,i){
     if(i.constructor === Array){
        var value = findLongestStr(i);
        console.log("value array => ",value);
        if(o.length < value.length){
          o = value;
        }
     }else{
           console.log("value i => ",i);
        if(o.length < i.length){
          o = i;
        }
     }
     return o;
  },"");
}

console.log("max length => ",findLongestStr(myArray));

Working jsFiddle demo - https://jsfiddle.net/k4yo35hb/1/

The main problem with you code is that you redefine longestStr each time the recursive function is called. Leaving you no way of comparing the longest string from each recursive call.

Using reduce() is a nice way to find the max of a regular un-nested array. You can add a little bit of recursion and still use reduce() for this which takes care of maintaining state between recursions because all the recursion unwinds within the reduce function:

 let myArray = ['ABC','ABCD','ABCDE',['ABC','ABCABABA',['ABABABABABABABABAZZ'],'ABCABABASS',],'ABCDEFGH','ABABABABZZQ'] function longestString(arr) { return arr.reduce((longest, item) => { if (Array.isArray(item)) { let rec = longestString(item) if (rec.length > longest.length) longest = rec } else if (item.length > longest.length) longest = item; return longest }, '') } console.log(longestString(myArray)) 

关于@Adrian Brand干净的答案,这是解决方案:

const findMaxStringInArray = (array, lastMax = '' ) => array.reduce((curMax,item)=>typeof item === 'string'?  item.length > curMax.length? item : curMax :  findMaxStringInArray(item, curMax) ,lastMax);

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM