如何通过使用具有ES6功能JavaScript中的递归来打动面试官

There’s nothing as flashy and useful for JavaScript interviews than recursion.

对于JavaScript采访而言,没有什么比递归更华丽和有用的了。

If you just want to be impressive with recursion in JavaScript, here are some semi real-world (technical test type) examples.

如果您只想通过JavaScript的递归给人留下深刻的印象,这里有一些半现实世界(技术测试类型)的例子。

The short definition of a recursive solution to a problem (in computer science) is: don’t use iteration. This usually means a function has to call itself with a smaller instance of the same problem. It does this until it hits a trivial case (usually defined in the problem).

(在计算机科学中)问题的递归解的简短定义是:不要使用迭代。 这通常意味着函数必须使用较小的同一问题实例来调用自身。 它会一直这样做,直到遇到小问题(通常在问题中定义)。

Hence, recursion is composed of a couple of steps.

因此,递归由几个步骤组成。

In this post, we’ll discuss:

在这篇文章中,我们将讨论:

  • 🛰 Recursion to wrap sequential HTTP requests

    cur递归以包装顺序的HTTP请求
  • 📃 Count number of characters

    📃计算字符数

The examples for this post are also on ObervableHQ, which is a super cool tool that allows you to build JavaScript notebooks:

本文的示例也位于ObervableHQ上, ObervableHQ是一个超酷的工具,可让您构建JavaScript笔记本:

cur递归以包装顺序的HTTP请求 (🛰 Recursion to wrap sequential HTTP requests)

Say you need to get multiple pages from a REST API and you’re forced to use the native HTTPS module, (example here). In this situation, we’ll be fetching comments from the Reddit API.

假设您需要从REST API获取多个页面,并且被迫使用本机HTTPS模块( 此处为示例 )。 在这种情况下,我们将从Reddit API中获取评论。

With this API:

使用此API:

  • if there are more comments than fit in one response, it will return an after field in the data. This can be used as a query param in a request to get the next chunk of comments

    如果注释数量超出一个响应的大小,它将在数据中返回一个after字段。 这可以用作请求中的查询参数,以获取下一个注释块

  • if there are no more comments, after will be falsy

    如果没有更多评论, after将是虚假的

That defines our terminating and recursive cases. We fetch data from the Reddit API and then either:

这定义了我们的终止和递归案例。 我们从Reddit API获取数据,然后执行以下任一操作:

  • after is falsy → terminating case, return the data

    错误→ 终止 after ,返回数据

  • after is defined → recursive case, pass it to fetch the next page as well as data returned from the current call

    after定义之后→ 递归的情况下 ,将其传递以获取下一页以及当前调用返回的数据

One of the tricks used here is passing an empty data array into the recursiveCommentFetch function from the first pass. This allows us to keep injecting more and more values as we go through each recursive call. We are able to resolve to the full set at the terminating case.

这里使用的技巧之一是从第一遍开始将一个空data数组传递到recursiveCommentFetch函数中。 这使我们在进行每个递归调用时可以不断注入越来越多的值。 我们能够解决终止案件中的全部问题。

const fetch = require('node-fetch');
const user = 'hugo__df';
function makeRedditCommentUrl(user, queryParams) {
  return `https://www.reddit.com/user/${user}/comments.json?${
    Object.entries(queryParams)
      .filter(([k, v]) => Boolean(v))
      .map(
        ([k, v]) => `${k}=${v}`
      ).join('&')
  }`;
}
function recursiveCommentFetch(user, data = [], { after, limit = 100 } = {}) {
  const url = makeRedditCommentUrl(user, { after, limit });
  return fetch(url)
    .then(res => res.json())
    .then(res => {
      const { after, children } = res.data;
      const newData = [...data, ...children];
      if (after) {
        // recursive case, there's a way to fetch more comments
        return recurseCommentFetch(user, newData, { after });
      }
      // base or terminating case
      return newData;
    });
}
recursiveCommentFetch(user)
  .then(comments => console.log(comments));

I familiarized myself with this API by creating the following visualization for Reddit contributions (in GitHub’s contribution graph style). See it here. The blog version is also live.

通过为Reddit贡献创建以下可视化(以GitHub的贡献图样式),我熟悉了此API。 在这里看到它 。 该博客版本也已上线

📃计算字符数 (📃 Count number of characters)

When the question goes something like this: “given an input, return an object containing how many times each character is present in the input” you’ll use this method.

当问题是这样的:“给定输入,返回一个对象,其中包含每个字符在输入中出现的次数”,您将使用此方法。

There’s a live demo here.

这里有一个现场演示

The terminating and recursive case isn’t immediately obvious, so there are a few leaps here:

终止和递归的情况并不立即明显,因此这里有一些飞跃:

  1. understanding that an input can be cast to a string, which can be .split into an Array (ie. most arbitrary input can be converted into an Array).

    理解,一个输入可被转换为一个字符串,它可以是.split成阵列(即,最任意输入可被转换成一个阵列)。

  2. knowing how to recurse through an Array. It’s probably one of the easier/most common things to recurse through. But it takes seeing it a couple of times to start feeling comfortable doing it.

    知道如何通过数组递归。 这可能是最容易/最常见的事情之一。 但是需要花很多时间才能开始感到舒服。

That gives us the following situation for a recursive function:

这给了我们递归函数的以下情况:

  • list/array of characters is empty → terminating case, return the characterToCount map

    字符列表/数组为空→ 终止大小写 ,返回characterToCount映射

  • list/array of characters is not empty → recursive case, update characterToCountMap by incrementing/ initializing the current character’s entry. Call the recursive function with the updated map and the rest of the list/array.

    字符列表/数组不为空→ 递归的情况下 ,通过增加/初始化当前字符的条目来更新characterToCountMap 。 使用更新后的地图和列表/数组的其余部分调用递归函数。

I’ve written a more complete post: Recursion in JavaScript with ES6, destructuring and rest/spread, which goes into more detail (examples and techniques) about how we can recurse through lists (arrays) in ES6 JavaScript. It explains things like the [firstCharacter, ...rest] notation.

我写了一篇更完整的文章: 使用ES6在JavaScript中进行递归,解构和rest / spread ,它详细介绍了如何在ES6 JavaScript中通过列表(数组)进行递归。 它解释了[firstCharacter, ...rest]表示法之类的内容。

function recurseCountCharacters(
  [firstCharacter, ...rest],
  characterToCountMap = {}
) {
  const currentCharacterCount = characterToCountMap[firstCharacter] || 0;
  const newCharacterToCountMap = {
    ...characterToCountMap,
    [firstCharacter]: currentCharacterCount + 1
  };
  
  if (rest.length === 0) {
    // base/terminating case
    // -> nothing characters left in the string
    return newCharacterToCountMap;
  }
  // recursive case
  return recurseCountCharacters(rest, newCharacterToCountMap);
}
function countCharacters(input) {
  return recurseCountCharacters(String(input).split(''));  
}
console.log(countCharacters(1000000));
// { "0":6, "1": 1 }
console.log(countCharacters('some sentence'));
// { "s":2,"o":1,"m":1,"e":4," ":1,"n":2,"t":1,"c":1}

That’s how you breeze through interviews using recursion 🙂, running circles around those toy problems.

这样一来,您便可以使用递归b轻松地进行采访,从而绕过那些玩具问题。

Recursive solutions to interview problems end up looking cooler and cleaner than iterative ones. They’re interviewer eye-candy.

采访问题的递归解决方案最终看起来比迭代解决方案更凉爽和干净。 他们是面试官眼中的糖果。

For any questions, you can reach me on Twitter @hugo__df.

如有任何疑问,您可以通过Twitter @hugo__df与联系

Get all the posts of the week before anyone else in your inbox: Code with Hugo newsletter.

在收件箱中的其他任何人面前获取一周中的所有帖子: 使用Hugo新闻通讯进行编码

翻译自: https://www.freecodecamp.org/news/how-to-impress-interviewers-by-using-recursion-in-javascript-with-es6-features-a14c763110d7/

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值