递归查找嵌套数组中的最后一个字符串?

Find last string in nested arrays recursively?

这些是数组:

[ 'markdown',
  [ 'para', 'this is a paragraph' ],
  [ 'para', {class: 'custom-class'}, 'another paragraph' ],
  [ 'hr' ],
  [ 'bulletlist',
    [ 'listitem', 'This is a list' ],
    [ 'listitem', 'This is another list' ] ] ]

我想做的是在每个字符串中找到最后一个字符串。在这种情况下,'this is a paragraph''another paragraph''This is a list''This is another list'。 (我对只有一个字符串的数组不感兴趣,在这种情况下,hr。但我想这是另一个 SO 问题。)

我能做到的最好的是:

for (i = 1; i < tree.length; i++) {
  var node = tree[i]
  var lastItem = node[node.length - 1] 

  console.log(lastItem)
}

\ this is a paragraph
\ {class: 'custom-class'}
\ hr
\ [ 'listitem', 'This is a list' ]
\ [ 'listitem', 'This is another list' ]

我认为您可以看出问题所在,尽管 1) 循环有时会找到嵌套的 array/object 2) 它不是递归的。

我应该如何修改循环以使其始终找到这些数组的最后一个字符串?

我有点难以理解您的对象结构,所以我首先给出一个措辞明确的答案。如果您的对象结构变得更清晰,我可以编写一个实际的编码示例。

这里不可能很难不使用递归,因为您不知道数组嵌套的深度。您需要做的是制作一个接收对象作为参数的函数。然后这个函数循环遍历对象的所有元素,如果发现其中任何一个是数组,则调用自身。当它到达最后一个元素时,它被打印出来。

基本上是这样的:

function findLastString(obj)
    loop obj.length
        if obj[i] == array
        then findLastString(obj[i])
    end loop
    if obj[obj.length-1] != array
    then print(obj[obj.length-1])
end function

使用带累加器的减速器和递归:

var findLast = function(xs) {
  return xs.reduce(function(acc, x) {
    if (Array.isArray(x)) {
      var last = x[x.length-1]
      if (Array.isArray(last)) {
        return acc.concat(findLast(x))
      }
      return acc.concat(last)
    }
    return acc
  },[])
}

console.log(findLast(yourArray))
/*^
[ 'this is a paragraph',
  'another paragraph',
  'hr',
  'This is a list',
  'This is another list' ]
*/

请注意,递归不是必需的,因为递归问题总是可以使用循环来解决,必要时还可以使用堆栈。递归更优雅,但在 JavaScript 中它会炸毁具有许多嵌套数组的堆栈(直到浏览器发布 TCO)但循环不会:

var findLast = function(xs) {
  var out = []
  for (var i = 0; i < xs.length; i++) {
    var x = xs[i]
    if (Array.isArray(x)) {
      var last = x[x.length-1]
      if (Array.isArray(last)) {
        xs = x
        i = 0
      } else {
        out.push(last)
      }
    }
  }
  return out
}

这解决了您描述的一般问题,但如果您想排除具有单个元素的数组,您需要再添加一个条件:

if (Array.isArray(x) && x.length > 1) {

演示: http://jsfiddle.net/e46wnbv3/