使用递归的一维数组迭代

时间:2018-10-11 14:56:48

标签: javascript arrays recursion

我正在尝试使用递归遍历一个简单的数组。对于此特定情况,我尝试使用递归方式重新创建.map()(不使用.map()!。目前,我只将原始数组中的最后一个元素推入,但我想将所有元素都推入数组

function recursiveMap (arr, func) {
    let newArr = [];
    if (arr.length === 1){
        newArr.push(func(arr));
    }
    else {
        newArr.push(...recursiveMap(arr.slice(1),func));
    }
    return newArr;
}

7 个答案:

答案 0 :(得分:4)

您需要在当前项目上使用func,并在数组的其余部分上扩展调用函数的结果:

function recursiveMap(arr, func) {
  return arr.length ? [func(arr[0]), ...recursiveMap(arr.slice(1), func)] : [];
}

const arr = [1, 2, 3];

const result = recursiveMap(arr, n => n * 2);

console.log(result);

答案 1 :(得分:2)

您的基本情况似乎是错误的。您将需要检查一个空数组:

function recursiveMap (arr, func) {
    let newArr = [];
    if (arr.length === 0) {
        // do nothing
    } else {
        newArr.push(func(arr[0]));
        newArr.push(...recursiveMap(arr.slice(1),func));
    }
    return newArr;
}

相反,当至少有一个元素时,您需要调用func(在第一项上)。

答案 2 :(得分:1)

通过递归,我发现使基本情况成为您检查函数的第一件事,并在那里缩短执行时间会很有帮助。 map的基本情况是数组有0个项目,在这种情况下,您将返回一个空数组。

如果在let [a, ...b]进行数组解构之前没有看到它,则a成为第一个值,b保留剩余的数组。您可以对slice执行相同的操作。

function recursiveMap(arr, func){
  if(arr.length == 0) return [];
  let [first, ...rest] = arr;
  return [func(first)].concat(recursiveMap(rest, func));
}

let test = [1,2,3,4,5,6,7];
console.log(recursiveMap(test, (item) => item * 2));

编辑

回到您的样本中,我很清楚地看到您在xD之前已经看到了销毁。不过,将其留在答案中供将来的读者阅读。

答案 3 :(得分:1)

以下是一些替代方案。每个recursiveMap

  • 不更改输入
  • 产生一个新数组作为输出
  • 当给出空输入[]时,
  • 会产生有效的结果
  • 使用单个纯函数表达式

解构任务

const identity = x =>
  x

const recursiveMap = (f = identity, [ x, ...xs ]) =>
  x === undefined
    ? []
    : [ f (x), ...recursiveMap (f, xs) ]
    
const square = (x = 0) =>
  x * x
  
console.log (recursiveMap (square, [ 1, 2, 3, 4, 5 ]))
// [ 1, 4, 9, 16, 25 ]


数组切片

const identity = x =>
  x

const recursiveMap = (f = identity, xs = []) =>
  xs.length === 0
    ? []
    : [ f (xs[0]), ...recursiveMap (f, xs.slice (1)) ]
    
const square = (x = 0) =>
  x * x
  
console.log (recursiveMap (square, [ 1, 2, 3, 4, 5 ]))
// [ 1, 4, 9, 16, 25 ]
  


具有默认分配的其他参数–创建较少的中间值

const identity = x =>
  x

const recursiveMap = (f = identity, xs = [], i = 0) =>
  i >= xs.length
    ? []
    : [ f (xs[i]) ] .concat (recursiveMap (f, xs, i + 1))
    
const square = (x = 0) =>
  x * x
  
console.log (recursiveMap (square, [ 1, 2, 3, 4, 5 ]))
// [ 1, 4, 9, 16, 25 ]


尾部递归(又可爱)

const identity = x =>
  x
  
const prepend = x => xs =>
  [ x ] .concat (xs)
  
const compose = (f, g) =>
  x => f (g (x))

const recursiveMap = (f = identity, [ x, ...xs ], then = identity) =>
  x === undefined
    ? then ([])
    : recursiveMap
        ( f
        , xs
        , compose (then, prepend (f (x)))
        )

const square = (x = 0) =>
  x * x

console.log (recursiveMap (square, [ 1, 2, 3, 4, 5 ]))
// [ 1, 4, 9, 16, 25 ]
// => undefined

recursiveMap (square, [ 1, 2, 3, 4, 5 ], console.log)
// [ 1, 4, 9, 16, 25 ]
// => undefined

recursiveMap (square, [ 1, 2, 3, 4, 5 ])
// => [ 1, 4, 9, 16, 25 ]


源自尾递归foldl –注意foldl选择了上面使用的类似技术:具有默认赋值的其他参数。

const identity = x =>
  x

const foldl = (f = identity, acc = null, xs = [], i = 0) =>
  i >= xs.length
    ? acc
    : foldl
        ( f
        , f (acc, xs[i])
        , xs
        , i + 1
        )

const recursiveMap = (f = identity, xs = []) =>
  foldl
    ( (acc, x) => acc .concat ([ f (x) ])
    , []
    , xs
    )
    
const square = (x = 0) =>
  x * x
  
console.log (recursiveMap (square, [ 1, 2, 3, 4, 5 ]))
// [ 1, 4, 9, 16, 25 ]

答案 4 :(得分:0)

欢迎堆栈溢出。您可以像以下示例一样将结果传递给自身:

function recursiveMap (arr, func,result=[]) {
  if (arr.length === 0){
      return result;
  }
  return recursiveMap(
      arr.slice(1),
      func,
      result.concat([func(arr[0])])
    );
}
console.log(recursiveMap([1,2,3,4],x=>(x===3)?['hello','world']:x+2));

或在函数中定义递归函数:

function recursiveMap (arr, func) {
  const recur = (arr, func,result=[])=>
    (arr.length === 0)
      ? result
      : recur(
        arr.slice(1),
        func,
        result.concat([func(arr[0])])
      );
  return recur(arr,func,[])
}
console.log(recursiveMap([1,2,3,4],x=>(x===3)?['hello','world']:x+2));

答案 5 :(得分:0)

您可以通过使用第三个参数作为收集的值来采用另一种方法。

function recursiveMap(array, fn, result = []) {
    if (!array.length) {
        return result;
    }
    result.push(fn(array[0]));
    return recursiveMap(array.slice(1), fn, result);
}

console.log(recursiveMap([1, 2, 3, 4, 5], x => x << 1));
console.log(recursiveMap([], x => x << 1));

答案 6 :(得分:-2)

添加newArr.push(func(arr[0]));,然后再次调用该函数

function recursiveMap (arr, func) {
    let newArr = [];
    if (arr.length === 1){
        newArr.push(func(arr));
    }
    else {
        newArr.push(func(arr[0]));
        newArr.push(...recursiveMap(arr.slice(1),func));
    }
    return newArr;
}

console.log(recursiveMap([1,2,3], function(a){return +a+2}))


相同但经过修改的答案,已纠正错误

function recursiveMap (arr, func) {
    let newArr = [];
    if(arr.length){
       newArr.push(func(arr[0]));
       if(arr.length > 1){
          newArr.push(...recursiveMap(arr.slice(1),func));
      }
    }
    return newArr;
}

console.log(recursiveMap([1,2,3], function(a){return a+2}))