【问题标题】:Recursively Reverse the Elements in an Array递归反转数组中的元素
【发布时间】:2015-01-18 00:54:07
【问题描述】:

我想在 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;
}

【问题讨论】:

  • 有什么理由不使用 javascript 已有的 revers() 函数?
  • 您的问题是什么?另请阅读this。还有一个长度为 1. 的子数组怎么需要反转 2. 以后需要反转
  • 哇,这些 cmets 和答案。你有一个错字。 lastOfIndex 而不是 lastIndexOf 我不确定这些其他用户在吸什么。 (但您的代码不起作用)
  • 好吧,我在抽“让我们尝试帮助新手学习递归”的烟斗,而不是仅仅修复无效代码中的拼写错误... :)
  • 让我们都抽那个烟斗:)。不过说真的,所有这些帮助都值得赞赏。我需要进入程序员的心态......

标签: javascript arrays recursion


【解决方案1】:

一个经典的递归实现是

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 必须保留堆栈来调用 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)));
}

或者如果你喜欢

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

这不是很干净,但给我们带来的好处是能够递归地思考,而没有与递归相关的正常堆栈开销。

【讨论】:

    【解决方案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;
    }
    

    【讨论】:

    • 如果要返回一个新的数组实例,修改传递的初始数组可能不是一个好主意。
    【解决方案3】:
    const recursiveRev = arr => arr.length === 0 || arr.length === 1 ? arr : arr.slice(arr.length-1).concat(recursiveRev(arr.slice(-arr.length, -1)));
    

    【讨论】:

    • 请详细说明您的答案。其他人很难理解为什么该代码会起作用。
    【解决方案4】:

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

    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));

    【讨论】:

      【解决方案5】:

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

      const reverse = ([x, ...xs]) =>
        x == undefined ? [] : [... reverse (xs), x]
      
      console .log (reverse ([9, 0, 3, 5, 7, 6, 8]))

      【讨论】:

        【解决方案6】:

        这就是我的处理方式:

        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】:

          试试

          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)) + "]"
          })
          &lt;pre&gt;[1,2,3,4,5,6,7]&lt;/pre&gt;&lt;button&gt;click&lt;/button&gt;

          【讨论】:

            【解决方案8】:

            这是我处理原始数组的解决方案。

               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/

            【讨论】:

              【解决方案9】:
              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)
              

              【讨论】:

                【解决方案10】:

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

                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 的“递归思考”。

                【讨论】:

                  【解决方案11】:

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

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

                  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))

                  【讨论】:

                    猜你喜欢
                    • 1970-01-01
                    • 1970-01-01
                    • 1970-01-01
                    • 2012-10-20
                    • 1970-01-01
                    • 1970-01-01
                    相关资源
                    最近更新 更多