【问题标题】:How to solve this with high order functions?如何用高阶函数解决这个问题?
【发布时间】:2021-02-24 05:38:16
【问题描述】:

我需要知道如何解决我从网上看到的这个问题。

对于给定的数组,我需要找到所有唯一元素并且减去 10。然后对所有元素进行求和。然后将每个数组值乘以这个数字(求和)。

我假设我可以使用 reduce 进行求和并使用 map 进行乘法,但我真的不知道它是如何工作的,我被卡住了。也不容易找到独特的元素。

我有输入值和预期值。

Input, expected  
[1], [1]  
[1, 1, 2], [2, 2, 4]  
[0, 0, 1, 2, 1], [0, 0, 2, 4, 2]  
[0, 10, 1, 1, 20, 3, 40, 3], [0, 0, 0, 0, 0, 0, 0, 0]  
[0, 1, 1, 2, 4, 11], [0, 6, 6, 12, 24, 66]  
[10, 1, 1, 1], [0, 0, 0, 0]  
[10, 11, 1, 2, 3, 4], [100, 110, 10, 20, 30, 40]

我正在尝试一些事情,但主要问题是我不理解我认为的语法。我知道如何通过循环来解决这个迭代问题,但我想通过高阶函数来学习。

这不是学校项目,我正在学习这个,所以我不需要解决方案,我想了解,谢谢。

我尝试的是像这样应用地图。并且还可以过滤和减少

var input = [0, 0, 1, 2, 1]
var output = [0, 0, 2, 4, 2]

var map, reduce, filter;
map = input.map(multiplyFunction(first,second))

function multiplyFunction(first,second){
    return first*second
}

【问题讨论】:

  • 我建议从文档和他们拥有的示例开始:Array#mapArray#reduce。尝试一下,遇到困难时再回来。
  • “总结”不是一个词。你的意思是“求和”吗?
  • 这个"和负10。"是什么意思?
  • 我猜他们的意思是“小于 10”。
  • 如果您发布您尝试过的内容,我们可以帮助您修复它。但除此之外,这个问题将被关闭,因为没有具体的问题。

标签: javascript node.js arrays


【解决方案1】:

您可以将想要的结果分成两部分,一个用于获取唯一值的因子,另一个用于将新值与该因子映射。

getSumOfUnique

因子函数迭代值并继续获取不需要的值。

此函数使用一个对象来计算所见值并使用一个变量来对唯一值求和。

这通过两种方式发生:

  1. 如果该值以前从未见过,则添加该值
  2. 如果该值只出现一次,则减去该值。

最后将sum作为factor返回给调用函数。

multiply

映射函数首先获取因子,并使用Array#map 映射新产品。

function getSumOfUnique(array) {
    let seen = {},
        sum = 0;
    
    for (const value of array) {
        if (value >= 10) continue;
        if (!seen[value]) {
            seen[value] = 1;
            sum += value;
            continue;
        }
        if (seen[value] === 1) {
            seen[value]++;
            sum -= value;
        }
    }
    return sum;
}

function multiply(array) {
    const factor = getSumOfUnique(array);
    return array.map(value => value * factor);
}

console.log(...multiply([1]));
console.log(...multiply([1, 1, 2]));
console.log(...multiply([0, 0, 1, 2, 1]));
console.log(...multiply([0, 10, 1, 1, 20, 3, 40, 3]));
console.log(...multiply([0, 1, 1, 2, 4, 11]));
console.log(...multiply([10, 1, 1, 1]));
console.log(...multiply([10, 11, 1, 2, 3, 4]));

最后是一个函数式的方法,使用

  • less10 用于检查 Array#filter 的值是否小于 10
  • unique 用于通过检查 filter 的值的索引来仅获取唯一值,
  • add 一个增加值的函数,后来用于Array#reduce
  • multiplyBy,一个带有闭包的 IIFE (immediately-invoked function expression),后来用于 map
  • getArray 一个函数,它保存所有部分并使用先前计算的因子映射数组。

const
    less10 = value => value < 10,
    unique = (v, _, a) => a.indexOf(v) === a.lastIndexOf(v),
    add = (a, b) => a + b,
    multiplyBy = factor => value => factor * value,
    getArray = array => array.map(multiplyBy(array
        .filter(less10)
        .filter(unique)
        .reduce(add, 0)
    ));

console.log(...getArray([1]));
console.log(...getArray([1, 1, 2]));
console.log(...getArray([0, 0, 1, 2, 1]));
console.log(...getArray([0, 10, 1, 1, 20, 3, 40, 3]));
console.log(...getArray([0, 1, 1, 2, 4, 11]));
console.log(...getArray([10, 1, 1, 1]));
console.log(...getArray([10, 11, 1, 2, 3, 4]));

【讨论】:

  • 谢谢我会检查并理解这个,但是只有地图吗?
  • 请参阅第二种方法。
  • 太棒了!非常感谢您的解释。由于我的声誉,我无法投票,但三个答案对我有帮助,如果你愿意,请随时在你们自己之间投票!
【解决方案2】:

您好,欢迎来到 StackOverflow。

首先,我认为开始理解语法的一个好点是检查 w3 示例:filtermapreduce。 或 Mozilla 示例:filtermapreduce

尝试这些示例并尝试理解每个步骤。

你的练习需要这三个功能,所以作为一个概述,我们可以这样定义每一个(也许这太不正式了):

  • 过滤器:使用过滤器创建一个新数组。
  • 映射:将每个值都放入数组中(即映射从一个数组到另一个数组的值)。
  • 减少:减少数组为唯一元素。

所以……为了你的锻炼。

短语本身解释了要使用的功能。检查这个:

我需要找到所有唯一元素且小于 10

意思是:“我需要将filterreturn unique &amp;&amp; x &lt; 10 之类的函数一起使用。”

然后做总结

所以...简化为一个独特的元素。就像“然后用return currentValue + nextValue这样的功能做reduce

然后将每个数组值乘以这个数字

这就像:“然后将每个值映射为value*=sumatory

仅此而已!容易,对吧?现在让我们翻译成代码。

假设您有一个这样的数组:[10, 11, 1, 2, 3, 4](示例中的最后一个)

首先您需要使用filter找到唯一值和 独特的位置有一个窍门。如果您比较一个数字的第一个和最后一个索引并且它是相同的值,那么... 是唯一的。所以函数是这样的

var array = [10, 11, 1, 2, 3, 4]
var filter = array.filter(x => (array.indexOf(x) === array.lastIndexOf(x) && x < 10))
console.log(filter) // [ 1, 2, 3, 4 ] 

但是没有唯一的方法可以做到这一点。您可以创建一个Set 以不重复值,计算每个值以获得具有count=1 或其他值的值,这是您的决定。我选择这个是因为我认为这是最好的方式。

语法很容易阅读:对于数组中的每个值,命名为x 然后执行=&gt; 函数。在这种情况下比较索引并比较是&lt;10

请注意,在您的示例中,您缺少 (x) =&gt;,因此您无法将变量传递给您的函数。

下一步...reduce

var reduce = filter.reduce((a, b) => a + b, 0)
console.log(reduce) // 10

简单。在输出数组中使用reduce
这里的sintaxys 是:“使用当前值a 和下一个值b,执行=&gt; 函数a+b0 开始”。换句话说……做总结。

最后一步:Map

var map = array.map((m) => {
    return m * reduce
})
console.log(map) // [ 100, 110, 10, 20, 30, 40 ]

在这里你是说:“对于数组中的每个值,m,执行一个函数=&gt;{...},乘以总和m * reduce。”

现在:一起行动!!

是的,(真的)最后一步,只替换函数的变量。

你看到reduce的地方放filter.reduce((a, b) =&gt; a + b, 0)
并且哪里有filter设置array.filter(x =&gt; (array.indexOf(x) === array.lastIndexOf(x) &amp;&amp; x &lt; 10))

var map = array.map((m) => {
    return m * (array.filter(x => (array.indexOf(x) === array.lastIndexOf(x) && x < 10))).reduce((a, b) => a + b, 0)
})

仅此而已。

希望对了解如何使用这些功能以及如何解决这些问题有所帮助。

看看你尝试了什么之后,检查示例并注意你需要使用(var) =&gt;获取变量。

还有一个sn-p

var array = [10, 11, 1, 2, 3, 4]
var map = array.map((m) => {
    return m * (array.filter(x => (array.indexOf(x) === array.lastIndexOf(x) && x < 10))).reduce((a, b) => a + b, 0)
})
console.log(map)

【讨论】:

    【解决方案3】:

    欢迎 V.D.我也是一个 JS 菜鸟,但是这个,我想我明白了 ;)

    您想先过滤掉您的值,因此 Array.filter 方法允许您这样做,而无需任何繁琐的 for 循环,如下所示:

    const array = [10, 11, 3, 20, 5];
    const lesserThanTen = array.filter(element => element < 10);
    console.log(lesserThanTen) //[3, 5]
    

    reduce() 函数的语法要求您首先定义要应用于数组中项目的函数,如下所示:

    function myFunc(total, num) {
      return total + num; // this will return the sum of the two numbers it receives
    } 
    // The reduce() method applies this to the array until it is just a single value
    
    var reducedNumbers = lesserThanTen.reduce(myFunc);
    

    获得过滤后的数组和求和后,您可以继续将所有内容乘以后一个数字。

    var x = lesserThanTen.map(multiplyBySummatory)
    

    这应该足以让您到达那里;)

    【讨论】:

    • 感谢您的回答。由于我的声誉,我无法投票,但三个答案对我有帮助,如果你愿意,请随时在你们自己之间投票!
    猜你喜欢
    • 2019-02-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-04-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多