pie.htc 使用_使用Apple Pie了解Array.prototype.reduce()和递归

pie.htc 使用

I was having trouble understanding reduce() and recursion in JavaScript, so I wrote this article to explain it to myself (hey, look, recursion!). These concepts share some similarities with making apple pies. I hope you find my examples both helpful and delicious.

我在理解JavaScript中的reduce()和递归时遇到了麻烦,因此我写了这篇文章向自己解释(嘿,看,递归!)。 这些概念与制作苹果派有一些相似之处。 希望您发现我的示例对您有帮助,也很美味。

Given an array with nested arrays:

给定一个带有嵌套数组的数组:

var arr = [1, [2], [3, [[4]]]]

We want to produce this:

我们要产生这个:

var flat = [1, 2, 3, 4]

使用for循环和if语句 (Using for loops and if statements)

If we know the maximum number of nested arrays we’ll encounter (there are 4 in this example), we can use for loops to iterate through each array item, then if statements to check whether that item is in itself an array, and so on…

如果我们知道将要遇到的最大嵌套数组数(在此示例中为4),则可以使用for循环遍历每个数组项,然后使用if语句检查该数组本身是否为数组,依此类推。上…

function flatten() {
    var flat = [];
    for (var i=0; i<arr.length; i++) {
    if (Array.isArray(arr[i])) {
        for (var ii=0; ii<arr[i].length; ii++) {
        if (Array.isArray(arr[i][ii])) {
            for (var iii=0; iii<arr[i][ii].length; iii++) {
            for (var iiii=0; iiii<arr[i][ii][iii].length; iiii++) {
                if (Array.isArray(arr[i][ii][iii])) {
                flat.push(arr[i][ii][iii][iiii]);
                } else {
                flat.push(arr[i][ii][iii]);
                }
            }
            }
        } else {
            flat.push(arr[i][ii]);
        }
        }
    } else {
    flat.push(arr[i]);
    }
    }
}

// [1, 2, 3, 4]

…Which works, but is both hard to read and harder to understand. Besides, it only works if you know how many nested arrays to process, and can you imagine having to debug this mess?! (Gee, I think there’s an extra i somewhere.)

…虽然有效,但既难以阅读,也难以理解。 此外,它只有在您知道要处理多少个嵌套数组的情况下才能起作用,并且您能想象必须调试此混乱吗?! (Gee,我认为i某个地方还有i 。)

使用减少 (Using reduce)

JavaScript has a couple methods we can use to make our code more concise and easier to follow. One of these is reduce() and it looks like this:

JavaScript有两种方法可用于使代码更简洁,更易于遵循。 其中之一是reduce() ,它看起来像这样:

var flat = arr.reduce(function(done,curr){
    return done.concat(curr);
}, []);

// [ 1, 2, 3, [ [ 4 ] ] ]

It’s a lot less code, but we haven’t taken care of some of the nested arrays. Let’s first walk through reduce() together and examine what it does to see how we’ll correct this.

它的代码要少得多,但是我们没有处理一些嵌套数组。 让我们首先一起完成reduce()并检查它的作用,看看我们将如何纠正它。

Array.prototype.reduce()

Array.prototype.reduce()

The reduce() method applies a function against an accumulator and each element in the array (from left to right) to reduce it to a single value. (MDN)

reduce()方法对一个累加器和数组中的每个元素(从左到右)应用一个函数,以将其减小为单个值。 (MDN )

It’s not quite as complicated as it seems. Let’s think of reduce() as an out-of-work developer (AI took all the dev jobs) with an empty basket. We’ll call him Adam. Adam’s main function is now to take apples from a pile, shine them up, and put them one-by-one into the basket. This basket of shiny apples is destined to become delicious apple pies. It’s a very important job.

它看起来并不复杂。 让我们把reduce()想象成一个工作空缺的开发人员(AI承担了所有开发工作)。 我们称他为亚当。 亚当的主要功能是从一堆苹果中取出苹果,将它们照亮,然后将它们一一装进篮子。 这篮子闪亮的苹果注定会变成美味的苹果派。 这是非常重要的工作。

In our above example, the pile of apples is our array, arr. Our basket is done, the accumulator. The initial value of done is an empty array, which we see as [] at the end of our reduce function. The apple that Adam is currently shining, you guessed it, is curr. Once Adam processes the current apple, he places it into the basket (.concat()). When there are no more apples in the pile, he returns the basket of polished apples to us, and then goes home to his cat.

在上面的示例中,一堆苹果就是我们的数组arr 。 我们的篮子done ,累加器。 done的初始值是一个空数组,在reduce函数末尾,我们将其视为[] 。 您猜想,亚当当前发光的苹果是curr 。 一旦Adam处理了当前的苹果, .concat()其放入购物篮( .concat() )。 当堆里没有更多的苹果时,他将一篮子打磨好的苹果退还给我们,然后回家养猫。

递归使用reduce来解决嵌套数组 (Using reduce recursively to address nested arrays)

So that’s all well and good, and now we have a basket of polished apples. But we still have some nested arrays to deal with. Going back to our analogy, let’s say that some of the apples in the pile are in boxes. Within each box there could be more apples, and/or more boxes containing smaller, cuter apples.

一切都很好,现在我们有一篮子抛光的苹果了。 但是我们仍然需要处理一些嵌套数组。 回到我们的类比,假设堆中的一些苹果放在盒子里。 在每个盒子里可能有更多的苹果,和/或有更多的盒子,里面装有更小的可爱的苹果。

Here’s what we want our apple-processing-function/Adam to do:

这是我们希望apple-processing-function / Adam要做的事情:

  1. If the pile of apples is a pile of apples, take an apple from the pile.

    如果一堆苹果是一堆苹果,请从这堆苹果中取出一个。
  2. If the apple is an apple, polish it, put it in the basket.

    如果苹果是苹果,则将其擦亮,放入篮子。
  3. If the apple is a box, open the box. If the box contains an apple, go to step 2.

    如果苹果是一个盒子,请打开盒子。 如果包装盒中包含一个苹果,请转到步骤2。
  4. If the box contains another box, open this box, and go to step 3.

    如果该框包含另一个框,请打开此框,然后转到步骤3。
  5. When the pile is no more, give us the basket of shiny apples.

    当不再堆满时,请给我们一篮子闪亮的苹果。
  6. If the pile of apples is not a pile of apples, give back whatever it is.

    如果那堆苹果不是一堆苹果,那就把它归还。

A recursive reduce function that accomplishes this is:

实现此目的的递归化简函数是:

function flatten(arr) {
  if (Array.isArray(arr)) {
  return arr.reduce(function(done,curr){
    return done.concat(flatten(curr));
    }, []);
  } else {
    return arr;
  }
}

// [ 1, 2, 3, 4 ]

Bear with me and I’ll explain.

忍受我,我会解释。

Recursion

递归

An act of a function calling itself. Recursion is used to solve problems that contain smaller sub-problems. A recursive function can receive two inputs: a base case (ends recursion) or a recursive case (continues recursion). (MDN)

函数调用自身的行为。 递归用于解决包含较小子问题的问题。 递归函数可以接收两个输入:基本案例(结束递归)或递归案例(继续递归)。 (MDN )

If you examine our code above, you’ll see that flatten() appears twice. The first time it appears, it tells Adam what to do with the pile of apples. The second time, it tells him what to do with the thing he’s currently holding, providing instructions in the case it’s an apple, and in the case it’s not an apple. The thing to note is that these instructions are a repeat of the original instructions we started with - and that’s recursion.

如果检查上面的代码,您会看到flatten()出现了两次。 第一次出现时,它告诉亚当如何处理这堆苹果。 第二次告诉他如何处理他当前持有的东西,如果是苹果,则提供说明,如果不是苹果,则提供说明。 需要注意的是,这些指令是我们最初使用的原始指令重复 -这就是递归。

We’ll break it down line-by-line for clarity:

为了清楚起见,我们将其逐行细分:

  1. function flatten(arr) { - we name our overall function and specify that it will take an argument, arr.

    function flatten(arr) { -我们命名整体函数,并指定它将接受参数arr

  2. if (Array.isArray(arr)) { - we examine the provided “arrgument” (I know, I’m very funny) to determine if it is an array.

    if (Array.isArray(arr)) { -我们检查提供的“ arrgument”(我知道,我很有趣)以确定它是否为数组。

  3. return arr.reduce(function(done,curr){ - if the previous line is true and the argument is an array, we want to reduce it. This is our recursive case. We’ll apply the following function to each array item…

    return arr.reduce(function(done,curr){ -如果上一行为true并且参数是一个数组,我们要减少它。这是递归的情况。我们将以下函数应用于每个数组项...

  4. return done.concat(flatten(curr)); - an unexpected plot twist appears! The function we want to apply is the very function we’re in. Colloquially: take it from the top.

    return done.concat(flatten(curr)); -出现意外的情节扭曲! 我们要应用的功能正是我们所处的功能。通俗地说:从顶部开始。

  5. }, []); - we tell our reduce function to start with an empty accumulator (done), and wrap it up.

    }, []); -我们告诉我们的reduce函数从一个空的累加器( done )开始,然后将其包装起来。

  6. } else { - this resolves our if statement at line 2. If the provided argument isn’t an array…

    } else { -这将解决第2行的if语句。如果提供的参数不是数组…

  7. return arr; - return whatever the arr is. (Hopefully a cute apple.) This is our base case that breaks us out of recursion.

    return arr; -返回任何arr 。 (希望是一个可爱的苹果。)这是使我们脱离递归的基础案例。

  8. } - end the else statement.

    } -结束else语句。

  9. } - end the overall function.

    } -结束整体功能。

And we’re done! We’ve gone from our 24 line, 4-layers-deep nested for loop solution to a much more concise, 9 line recursive reduce solution. Reduce and recursion can seem a little impenetrable at first, but they’re valuable tools that will save you lots of future effort once you grasp them.

我们完成了! 我们已经从24线走了,4层深嵌套for循环解决方案更加简洁,9号线递归降低解决方案。 还原和递归起初似乎有些不可理解,但是它们是有价值的工具,一旦掌握了它们,它们将为您节省很多以后的工作。

And don’t worry about Adam, our out-of-work developer. He got so much press after being featured in this article that he opened up his very own AI-managed apple pie factory. He’s very happy.

不用担心我们失业的开发人员Adam。 在这篇文章中被介绍后,他获得了如此多的关注,他开设了自己的AI管理的苹果派工厂。 他很高兴。

Thanks for reading! You can find more articles explaining coding concepts with food on my blog.

谢谢阅读! 在我的博客上,您可以找到更多有关食物编码概念的文章

翻译自: https://www.freecodecamp.org/news/understanding-array-prototype-reduce-and-recursion-using-apple-pie-f60cde58ea51/

pie.htc 使用

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值