简体   繁体   中英

This question is about an exercise in the book Eloquent JavaScript

The last part to this exercise is to write a recursive function that takes two parameters, a joined list and an index respectively. The function will find the value in the object within the list at it's respective index. The code i have written works the way i want (i can see it working when i console.log for every occasion the function is called. But on the last occasion it refers undefined as my value. I cannot understand why. Oh and it works for index of 0. code as followed.

and first, list looks like this:

list = {
    value: 1,
    rest: {
        value: 2,
        rest: {
            value: 3,
            rest: null
            }
        }
    };



   const nth = (list, targetNum) => {
   let value = Object.values(list)[0];
   if (targetNum == 0) {
       return value;
   } else {
       targetNum = targetNum -1;
       list = Object.values(list)[1];
    //    console.log(value);
    //    console.log(targetNum);
    //    console.log(list);
       nth(list, targetNum);
   }
};
console.log(nth(arrayToList([1,2,3]),2)); 

below is the code for arrayToList it was the first part of the exercise and if you have any comments that's cool, cause the hints ended up suggesting to build the list from the end.

const arrayToList = (arr) => { 
    let list = {
        value: arr[0],
        rest: nestObject()
    };
    function nestObject() {
        let rest = {};
        arr.shift();
        const length = arr.length;
        if (length == 1) {
            rest.value = arr[0];
            rest.rest = null;
        } else {
            rest.value = arr[0];
            rest.rest = nestObject();
        }
        return rest;   
    }
    return list;
};

Both solutions are convoluted and unnecessary verbose. Actually, both functions could be one-liners. Here are a few hints:

For the toList thing consider the following:

  • if the input array is empty, return null (base case)

  • otherwise, split the input array into the "head" (=the first element) and "tail" (=the rest). For example, [1,2,3,4] => 1 and [2,3,4]

  • return an object with value equal to "head" and rest equal to toList applied to the "tail" (recursion)

On a more advanced note, the split can be done right in the function signature with destructuring:

const toList = ([head=null, ...tail]) => ...

Similarly for nth(list, N)

  • if N is zero, return list.value (base case)

  • otherwise, return an application of nth with arguments list.rest and N-1 (recursion)

Again, the signature can benefit from destructuring:

const nth = ({value, rest}, n) => 

Full code, if you're interested:

 const toList = ([value = null, ...rest]) => value === null? null: {value, rest: toList(rest)} const nth = ({value, rest}, n) => n === 0? value: nth(rest, n - 1) // let lst = toList(['a', 'b', 'c', 'd', 'e', 'f']) // or simply toList('abcdef') console.log(lst) console.log(nth(lst, 0)) console.log(nth(lst, 4))

You simply need to add a return when recursively calling nth . Otherwise the logic is carried out but no value is returned (unless targetNum is 0)

const nth = (list, targetNum) => {
   let value = Object.values(list)[0];
   if (targetNum == 0) {
       return value;
   } else {
       targetNum = targetNum -1;
       list = Object.values(list)[1];
       return nth(list, targetNum); // return needed here too
   }
};

Or more succinctly:

const nth = (list, n) => n === 0 ? list.value : nth(list.rest, n - 1)

Here's another non-recursive arrayToList that builds the list from the end:

const arrayToList = arr => arr.slice().reverse().reduce((rest, value) => ({value, rest}), null);

(The slice here is just to make a copy of the array so that the original is not reversed in place.)

Georg's recursive solutions are beautiful!

I'd like to add the hinted “build the list from the end” solution from the book :

const arrayToList => (arr) => {
  var list
  while (arr.length) {
    list = {value: arr.pop(), rest: list}
  }
  return list
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM