使用Javascript问题的递归问题

时间:2015-07-23 04:11:47

标签: javascript recursion

我正在从FreeCodeCamp

开始这个挑战
  

展平嵌套数组。你必须考虑到不同的水平   嵌套。

我正在尝试使用递归来解决它。

这是我的代码:

function steamroller(arr) {
    var flatArray = [];

    function flatten(obj) {
        if (!Array.isArray(obj)) {
            return(obj);
        }
        for (var i in obj) {
            return flatten(obj[i]);
        }
    }

    flatArray.push(flatten(arr));

    console.log(flatArray);
}

steamroller([1, [2], [3, [[4]]]]);

此日志:

Array [ 1 ]

我可以看到问题,return语句打破for循环,所以只返回第一个值。

但是如果我遗漏退货并且只使用:

flatten(obj[i]);

我回来了:

Array [ undefined ]

我该怎么做才能解决这个问题?

6 个答案:

答案 0 :(得分:3)

您需要将项目添加到结果数组中。

function flatten(arr){
  var flat = [];

  arr.forEach(function(item){     
    flat.push.apply(flat, Array.isArray(item) ? flatten(item) : [item]);      
  });

  return flat;
}

答案 1 :(得分:1)

我修改了你的代码以便它可以正常工作,添加注释:

function steamroller(arr) {
var flatArray = [];

function flatten(obj) {
    if (!Array.isArray(obj)) {
        // We got to the innermost element. Push it to the array.
        flatArray.push(obj); 
        return;
    }
    for (i = 0; i < obj.length; i++) {
        flatten(obj[i]); // Do not return here.
    }
}

flatten(arr);

console.log(flatArray);
}

steamroller([1, [2], [3, [[4]]]]);

答案 2 :(得分:1)

这是一种略有不同的方法:

function flat(a,f){
 if (!f) var f=[];
 a.forEach(function(e){
  if (Array.isArray(e)) flat(e,f);
  else f.push(e);
 });
 return f;
}

var flatArray=flat(deepArray);

该函数每次返回flattened数组,但忽略其自身内部调用中的返回值(flat(e,f))。相反,它会不断将每个非数组值推送到同一f - 最初在flat(a)外部调用中定义的数组。

使用第二个(通常是未使用的)参数,您还可以将值连接到已存在的平面数组,如

var a=[[2,4,[5,6,[7,8],[9,10]],1],3];
var fl1=flat(a);
// "2|4|5|6|7|8|9|10|1|3"
var fl2=flat(a,fl1);
// "2|4|5|6|7|8|9|10|1|3|2|4|5|6|7|8|9|10|1|3"

答案 3 :(得分:1)

完全递归解决方案,如果您不需要以保持原始数组的完整性:

function flatten (obj, memo) {
    memo = (memo || []);
    if (Array.isArray(obj)) {
        if (obj.length) {
            // flatten the first element, removing it from the original array
            flatten(obj.shift(), memo);
            // flatten the rest of the original array
            flatten(obj, memo);
        }
        return memo;
    }
    return memo.push(obj);
}

我们首先检查obj是否为数组。然后,如果它不是空的,将第一个元素弄平,则将其余部分弄平。如果object不是数组,则返回并推送到memo数组,返回。

请注意,在第一行我设置memo = (memo || [])。如果未设置memo,这可确保我们始终在第一次调用中获得新数组。

答案 4 :(得分:0)

function steamrollArray(arr) {

  let string = String(arr);
  let strArr = string.split(",");
      
  for (let i in strArr){

    if (strArr[i]==""){
      strArr.splice(i,1); 
      
    }

    if (strArr[i]=="[object Object]"){
      strArr[i] = {}; 
    }

    if (isNaN(parseInt(strArr[i],10))== false){
      strArr[i] = parseInt(strArr[i]); 
    }

  }

  return strArr;

}

答案 5 :(得分:0)

因为最近这是一个新答案,也许是时候重新审视它了。

这是一个相当简单的递归过程。当问到这个问题时,ES5随处可见,ES6 / ES2015随处可见。

一个简单的ES5解决方案如下所示:

const flat = (ns) => 
  ns .map (n => Array .isArray (n) ? flat (n) : n)
     .reduce ((a, b) => a .concat (b), [])

但是ES6不再需要此模式,并且map-reduce(concat)模式现在可以用Array.prototype.flatMap编写:

const flatter = (ns) => 
  ns .flatMap(n => Array .isArray (n) ? flatter (n) : n)

但是,您甚至不需要这样做,因为ES6还引入了Array.prototype.flat,这使我们可以编写以下代码:

const flattest = (ns) =>
  ns .flat (Infinity)

const flat = (ns) => 
  ns .map (n => Array .isArray (n) ? flat (n) : n)
     .reduce ((a, b) => a .concat (b), [])

const flatter = (ns) => 
  ns .flatMap(n => Array .isArray (n) ? flatter (n) : n)

const flattest = (ns) =>
  ns .flat (Infinity)


const data = [1, [2], [3, [[4]]]]

console .log (flat (data))
console .log (flatter (data))
console .log (flattest (data))