递归地反转数组中的元素

时间:2015-01-18 00:54:07

标签: javascript arrays recursion

我想在javascript中编写一个递归函数,返回一个反转元素的数组。此代码生成以下错误:

  

undefined不是函数

function reverseArray (toBeReversed){
  var reversed = [];

  function reverser (toBeReversed){
    if (toBeReversed.length == 1)
      reversed.push(toBeReversed[0]);
    else {
      reversed.push(toBeReversed.lastOfIndex(0)); //error on this line
      reverser(toBeReversed.slice(-1));
    }
  }

  reverser(toBeReversed);
  return reversed;
}

11 个答案:

答案 0 :(得分:3)

经典的递归实现将是

function reverse(a) {
    if (!a.length) return a;
     return reverse(a.slice(1)).concat(a[0]);
}

您不需要任何循环,数组累积值,函数内部的函数或任何其他机器。

如果您更喜欢编写小的单行代码以使代码更具可读性,那么

function head(a)    { return a[0];         }
function tail(a)    { return a.slice(1);   }
function push(a, v) { a.push(v); return a; }
function empty(a)   { return !a.length;    }

function reverse(a) { 
    if (empty(a)) return a;
    return push(reverse(tail(a)), head(a)); 
}

这个小程序具有可以“读”为英语的属性,我认为应该有更多的程序。在这种情况下,它是

  

如果数组为空,则数组的反转为(1)为空; (2)否则,将头部添加到尾部反向末​​端的结果。

不幸的是,即使在JS实现中提供优化的尾递归(此时精确地为none),在这种情况下也不会应用它,因为JS必须保持堆栈调用{{1每次都在concat的结果上。我们能写一些可以优化的东西吗?是的,通过携带另一个值,即到目前为止反转数组的结果:

reverse

或者如果您愿意

function unshift(a, v) { a.unshift(v); return a; }

function reverse(a) { return _reverse(a, []); }

function _reverse(a, result) {
    if (empty(a)) return result;
    return _reverse(tail(a), unshift(result, head(a)));
}

这不是很干净,但是给我们的好处是能够递归思考,而不会出现与递归相关的正常堆栈开销。

答案 1 :(得分:2)

lastOfIndex不是函数,你可能意味着使用lastIndexOf。这是一种类似的方式:

function reverseArray (toBeReversed){
  var reversed = [];

  function reverser (toBeReversed){
    if (toBeReversed.length !== 0){
      reversed.push( toBeReversed.pop() );
      reverser( toBeReversed );
    }
  }

  reverser(toBeReversed);
  return reversed;
}

答案 2 :(得分:1)

const recursiveRev = arr => arr.length === 0 || arr.length === 1 ? arr : arr.slice(arr.length-1).concat(recursiveRev(arr.slice(-arr.length, -1)));

答案 3 :(得分:1)

我通过使用递归得出了这个答案

function reverse(arr) {
    return (arr.length > 1) ? [arr.pop()].concat(reverse(arr)) : arr.pop();
}

const dataSet = [0, 1, 2, 3, 4];

console.log(reverse(dataSet));

答案 4 :(得分:1)

这一直在复活,但 this answer 似乎很少有任何改进。然而,在现代 JS 中,该算法有一个更好的语法:

const reverse = ([x, ...xs]) =>
  x == undefined ? [] : [... reverse (xs), x]

console .log (reverse ([9, 0, 3, 5, 7, 6, 8]))

答案 5 :(得分:0)

尝试

function reverseArray (arr) {
  return (function reverser(r, t) {
    r.push(t.splice(-1, 1)[0]);
    return !!t.length ? reverser(r, t) : r
  }([], arr));
};



function reverseArray (toBeReversed) {
  return (function reverser(r, t) {
r.push(t.splice(-1, 1)[0]);
return !!t.length ? reverser(r, t) : r
  }([], toBeReversed));
};

var rev = document.getElementsByTagName("pre")[0];
document.getElementsByTagName("button")[0]
.addEventListener("click", function(e) {
  rev.innerText = "[" + reverseArray(JSON.parse(rev.innerText)) + "]"
})

<pre>[1,2,3,4,5,6,7]</pre><button>click</button>
&#13;
&#13;
&#13;

答案 6 :(得分:0)

这就是我接近它的方式:

function reverse(arr) {
  var result = [];
  var count = arr.length;

  function recur() {
     if (result.length < arr.length) {
       result.push(arr[--count]);
       return recur();
     } else {
       return result;
     }
  }

  return recur();
}

用法:

var letters = ["a", "b", "c", "d", "e", "f", "g", "h"];
var reversed = reverse(letters);

输出:

console.log(reversed);
//=> ["h", "g", "f", "e", "d", "c", "b", "a"]

// Original array is unmodified
console.log(letters);
//=> ["a", "b", "c", "d", "e", "f", "g", "h"]

答案 7 :(得分:0)

这是我操作原始数组的解决方案。

   function reverseArr(arr, i, j){
      if(i < j){
        var temp1 = arr[i];
        arr[i] = arr[j];
        arr[j] = temp1;
        i++;
        j--;
        return reverseArr(arr,i,j);
      } else if(i === j ){
        return arr;
      }
    }
    var originalArr = [1,5,7,3,2,9,11];
    result = reverseArr(originalArr, 0, originalArr.length-1);
    console.log(result);

链接到小提琴:https://jsfiddle.net/octopuscode/opyes4nd/2/

答案 8 :(得分:0)

let arr = ["1","2","3"]; //declaration of array

function reverseArr(param){
  let i=param.length; //set counter i to the array length
  
  if(i==0){ //when to exit recursion
    return;
  }
  
  console.log(param[i-1]) //what to do until you exit,[i-1] because arrays are 0-based
  param.pop(param[i-1]) //pop already printed element from array
  
  reverseArr(param) //pass the new array and invoke function again
}

reverseArr(arr)

答案 9 :(得分:0)

使用递归实现一个非常简单的算法 -

I/P : ["h", "e", "l", "l", "o"] O/P: [ "o" , "l", "l", "e", "h" ]

想法:

如果我能以某种方式取出第一个元素并将其放入最后一个索引中,我的工作就完成了。

说明:

由于我们使用递归,我们可以将数组的第一个元素存储在堆栈中。

现在,我们知道 LIFO 上的堆栈工作。所以,按照上面的原则,如果我的数组的最后一个元素先入栈,如果我们可以先将最后一个元素压入一个空数组,那么我们就可以实现输出。

算法:

  1. 弹出数组的第一个元素
  2. 调用相同的函数,直到所有元素都被弹出并且数组为空。
  3. 推送空数组中最后弹出的元素。

代码:


    function reverseArray (s) {
    if(s.length === 0) { // base case of the recursion
        return []
    }

    let v = s.shift(); // Pop out the first element
    reverseArray(s); // repeat the operation for the next element
    s.push(v); // Once base case is reached start pushing the last popped element in the array
    return s;
}


console.log(reverseArray(["h" , "e", "l", "l" , "o"]))

注意:如果您不清楚递归的工作原理、调用堆栈是什么等。您可能需要阅读 Eric Roberts 的“Thinking Recursively”。

答案 10 :(得分:-1)

这是我对反向函数的解决方案:

  • 深。
  • 不改变输入数组。

function reverser = (array) => {
  const reversed = [];
  for (let i = array.length-1; i >= 0; i-- ) {
    if (Array.isArray(array[i])) {
      reversed.push(reverser(array[i]))
    } else {
      reversed.push(array[i])
    }
  }
  return reversed;
}

const arr1 = [1,2,3,4,5,6,7,8,9]
const arr2 = [[1,2,3],[4,5,6],[7,8,9]]
const arr3 = [[[1,2],[3]],[[4,5],[6]],[[7,8],[9]]]

console.log(reverser(arr1))
console.log(reverser(arr2))
console.log(reverser(arr3))