简体   繁体   English

Underscore.js-命令和功能练习

[英]Underscore.js - Imperative & Functional exercise

I'm learning about Underscore.js and the higher order functions. 我正在学习Underscore.js和高阶函数。 I came across the following problem, and I'm just simply stuck. 我遇到了以下问题,我只是被卡住了。

I'm not looking for a handout but at the same time, I don't have anywhere to turn for guidance in this. 我不是在寻找讲义,但与此同时,我没有任何地方可以寻求指导。 I would love someone to at least point me in the right direction. 我希望有人至少可以指出正确的方向。

What exactly does it mean by imperative vs functional? 命令式与功能性究竟是什么意思?

I don't even know where to start when it comes to completing the 'functional' solution. 对于完成“功能性”解决方案,我什至不知道从哪里开始。

Any helpful info on this subject would be so much appreciated. 任何有关此主题的有用信息将不胜感激。

Please note: I do understand what map(), flatten(), and reduce() do. 请注意:我确实了解map(),flatten()和reduce()的作用。 I just don't know how to apply it to this situation. 我只是不知道如何将其应用于这种情况。

I do NOT understand what 'functional' really means. 我不明白“功能”的真正含义。 I would love any insight. 我希望有任何见识。

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);

You need to break it down into parts. 您需要将其分解为几个部分。 First of all, you only care about the ingredients, but products contains a lot of extra information, so use map to just extract the ingredients. 首先,您只关心成分,但是products包含大量额外信息,因此请使用map提取成分。

Now you have ingredients in an array of arrays, but you just want one big array with all the ingredients, so use flatten to give you that. 现在,您可以将成分放在一组数组中,但是您只想要一个包含所有成分的大数组,因此可以使用flatten来实现。

Now you want to count the ingredients. 现在您要计算成分。 You can think of this as a series of reductions, where you have an object with the previous counts, and for this current item, you want to increment the count. 您可以认为这是一系列减少,您有一个具有先前计数的对象,而对于当前项目,您想要增加计数。 This can be done with a reduce that starts with an empty object. 这可以通过以空对象开始的reduce来完成。 I'll leave the implementation of the incrementCount function as an exercise for the reader. 我将把incrementCount功能的实现留给读者练习。

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

With functional code, think of your data as passing through a series of transformations, each one bringing you closer to your goal, rather than one big loop you try to cram all your mutations into. 使用功能代码,可以将您的数据视为经过一系列转换,每次转换都使您更接近目标,而不是一个试图将所有变异都塞入其中的大循环。

Functional means that every function that is called has a return value and usually no side effects ("pure"). 功能性意味着每个被调用的函数都具有返回值,并且通常没有副作用(“纯”)。 It is a programming style that is very suitable for data transformations. 这是一种非常适合数据转换的编程风格。

  • map takes an array and returns an array with each item transformed. map接受一个数组,并返回一个数组,其中每个项目都已转换。
  • reduce goes through the array, always providing the previously returned value and the next item in the array, calculating a new value. reduce遍历数组,始终提供先前返回的值和数组中的下一项,从而计算新值。 Can be used to calculate sums and such. 可用于计算总和等。
  • flatten makes a list of lists into just a list. 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); 

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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