【问题标题】:Underscore.js - Imperative & Functional exerciseUnderscore.js - 命令式和功能性练习
【发布时间】:2018-03-25 17:29:01
【问题描述】:

我正在学习 Underscore.js 和高阶函数。我遇到了以下问题,我只是卡住了。

我不是在寻找讲义,但与此同时,我没有任何地方可以寻求指导。我希望有人至少为我指明正确的方向。

命令式 vs 函数式到底是什么意思?

在完成“功能性”解决方案时,我什至不知道从哪里开始。

任何有关此主题的有用信息将不胜感激。

请注意:我确实了解 map()、flatten() 和 reduce() 的作用。我只是不知道如何将其应用于这种情况。

我不明白“功能性”的真正含义。我会喜欢任何见解。

var products = [
    {
        name: 'Sonoma',
        ingredients: ['artichoke', 'sundried tomatoes', 'mushrooms'],
        containsNuts: false,
    },
    {
        name: 'Pizza Primavera',
        ingredients: ['roma', 'sundried tomatoes', 'goats cheese', 'rosemary'],
        containsNuts: false,
    },
    {
        name: 'South Of The Border',
        ingredients: ['black beans', 'jalapenos', 'mushrooms'],
        containsNuts: false,
    },
    {
        name: 'Blue Moon',
        ingredients: ['blue cheese', 'garlic', 'walnuts'],
        containsNuts: true,
    },
    {
        name: 'Taste Of Athens',
        ingredients: ['spinach', 'kalamata olives', 'sesame seeds'],
        containsNuts: true,
    },
];

// Underscore.js

// Count the ingredient occurence

// IMPERATIVE example:
var ingredientCount = { "{ingredient name}": 0 };

for (i = 0; i < products.length; i += 1) {
    for (j = 0; j < products[i].ingredients.length; j += 1) {
        ingredientCount[products[i].ingredients[j]] =
            (ingredientCount[products[i].ingredients[j]] || 0) + 1;
    }
}

expect(ingredientCount['mushrooms')]).toBe(2);


// FUNCTIONAL: 
/* chain() together map(), flatten() and reduce() */

var ingredientCount = { "{ingredient name}": 0 };

// ? ? ?

expect(ingredientCount['mushrooms']).toBe(2);

【问题讨论】:

  • 您需要先会走路,然后才能跑步。对 mapfilterreduce(它们是标准 JS 数组类型的一部分,不是 Underscore 特定的)有一些基本的了解,将有助于您思考如何解决这个问题一种使用函数式方法的问题。
  • @AsadSaeeduddin 抱歉,我的帖子不清楚。我确实了解mapfilterreduce 的作用。我只是不明白它在这里是如何应用的,以及“功能”的实际含义。
  • en.wikipedia.org/wiki/Functional_programming。这里的相关性是,您将编写一个函数来执行所示的命令式、基于循环的转换,而不是使用数组组合器和纯函数。
  • 例如,“将数组中的每个元素乘以 2”的命令式解决方案是 const newArray = []; for (let i = 0; i &lt; oldArray.length; i++) { newArray.push(oldArray[i] * 2); }。功能解决方案为:const newArray = oldArray.map(i =&gt; i * 2).

标签: javascript functional-programming underscore.js imperative-programming


【解决方案1】:

您需要将其分解为多个部分。首先,你只关心成分,但是products包含很多额外的信息,所以使用map只是提取成分。

现在您在数组数组中有成分,但您只想要一个包含所有成分的大数组,所以使用 flatten 给您。

现在您要计算成分。您可以将其视为一系列减少,其中您有一个具有先前计数的对象,并且对于此当前项目,您希望增加计数。这可以通过以空对象开头的reduce 来完成。我将把 incrementCount 函数的实现留给读者练习。

const ingredients = _.map(products, p => p.ingredients);
const flatIngredients = _.flatten(ingredients);
const counts = _.reduce(flatIngredients, incrementCount, {});

使用函数式代码,将您的数据视为经过一系列转换,每一次转换都使您更接近目标,而不是您试图将所有突变塞入一个大循环。

【讨论】:

  • 这是一个很好的解释。这真的帮助我更好地理解它。非常感谢您抽出宝贵时间来解释这一点。
【解决方案2】:

函数式意味着被调用的每个函数都有一个返回值并且通常没有副作用(“纯”)。是一种非常适合数据转换的编程风格。

  • map 接受一个数组并返回一个数组,其中每个项目都经过转换。
  • reduce 遍历数组,始终提供先前返回的值和数组中的下一项,计算新值。可用于计算总和等。
  • flatten 将一个列表变成一个列表。

var products = [
    {
        name: 'Sonoma',
        ingredients: ['artichoke', 'sundried tomatoes', 'mushrooms'],
        containsNuts: false,
    },
    {
        name: 'Pizza Primavera',
        ingredients: ['roma', 'sundried tomatoes', 'goats cheese', 'rosemary'],
        containsNuts: false,
    },
    {
        name: 'South Of The Border',
        ingredients: ['black beans', 'jalapenos', 'mushrooms'],
        containsNuts: false,
    },
    {
        name: 'Blue Moon',
        ingredients: ['blue cheese', 'garlic', 'walnuts'],
        containsNuts: true,
    },
    {
        name: 'Taste Of Athens',
        ingredients: ['spinach', 'kalamata olives', 'sesame seeds'],
        containsNuts: true,
    },
];

const result = products.reduce((allIngredients, item) => allIngredients.concat(item.ingredients), [])
   .reduce((counts, ingredient) => { 
     counts[ingredient] ? counts[ingredient]++ : (counts[ingredient] = 1);
     return counts
   }, {})

console.log(result);

【讨论】:

    猜你喜欢
    • 2016-03-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-05-12
    • 2014-03-06
    • 1970-01-01
    • 2011-10-27
    • 2012-05-10
    相关资源
    最近更新 更多