2015-10-14 38 views
0

这是为了理解函数式编程。函数式编程示例

它来自一篇关于嫌杂志: http://www.smashingmagazine.com/2014/07/dont-be-scared-of-functional-programming/

嗨,我有以下数据

var data = [ 
    { 
    name: "Jamestown", 
    population: 2047, 
    temperatures: [-34, 67, 101, 87] 
    }, 
    { 
    name: "Awesome Town", 
    population: 3568, 
    temperatures: [-3, 4, 9, 12] 
    } 
    { 
    name: "Funky Town", 
    population: 1000000, 
    temperatures: [75, 75, 75, 75, 75] 
    } 
]; 

我需要在一个新的数组

平均气温和平均人口和商店
[ 
    [average temperature, average population] 
] 

我想解决这个问题的方法是使用两个for循环。为什么这是解决问题的不好方法?为什么函数式编程是答案?

+0

检查编辑 – Jasmine

+0

该杂志不应该解释为什么他们认为函数式编程是“答案”吗? – crush

回答

2

我想解决这个问题的方法是使用两个for循环。

命令式编程没有错。许多人喜欢用这种方式编写代码,而且对他们来说感觉很自然。但是,为什么不利用函数式编程的一些好处。

为什么这是解决问题的不好方法?

如上所述,它不一定解决问题,但是,让我们来看看他们使用的示例代码,一个糟糕的方式:

var coords = [], 
    totalTemperature = 0, 
    averageTemperature = 0; 

for (var i=0; i < data.length; i++) { 
    totalTemperature = 0; 

    for (var j=0; j < data[i].temperatures.length; j++) { 
    totalTemperature += data[i].temperatures[j]; 
    } 

    averageTemperature = totalTemperature/data[i].temperatures.length; 

    coords.push([averageTemperature, data[i].population]); 
} 

它解决了这个问题。现在,这里是一个功能更强大的方式相同的片段:

function average(sum, count) { 
    return sum/count; 
} 

function sum(x, y) { 
    return x + y; 
} 

var coords = data.map(function(item) { 
    return [ 
    average(item.temperatures.reduce(sum), item.temperatures.length), 
    item.population 
    ]; 
}); 

显然,作为@Fabio指出它可以更进一步采取但是,我想用相同的逻辑来告诉你一个简单的例子。

你觉得哪些比较容易推理,测试等?

为什么函数式编程的答案是?

函数式编程并不是JavaScript语言的一些灵丹妙药,但JavaScript的美妙之处在于我们可以利用其他语言的范例。

1

这里有一个(在许多方面做它)。当然,如average reducer而不是sum这样的更专用的reduce函数会增加代码的可读性,我认为这个版本在第一次迭代时更容易“自行提出”,然后可以进行细化。

function sum(a,b){return a+b;} 
function flatten(a,b){return a.concat(b);} 

    console.log([ 
     data.map(function(datum){ 
      return datum.temperatures; 
     }).reduce(flatten,[]).reduce(sum,0) 
     /data.map(function(datum){ 
      return datum.temperatures; 
     }).reduce(flatten,[]).length 
     , 
     data.map(function(datum){ 
      return datum.population; 
     }).reduce(sum,0) 
     /data.length 
]) 

现在,这里的一个更可读的,但稍硬versionn写:

function total(running,x){return {sum:running.sum+x, count:running.count+1};} 
function average(o){return o.sum/o.count;} 
function flatten(a,b){return a.concat(b);} 
function property(name){return function(x){return x[name];}} 
var startingTotal={sum:0,count:0}; 

[ 
average(data.map(property("temperatures")).reduce(flatten).reduce(total,startingTotal)), 
average(data.map(property("population")).reduce(total,startingTotal)) 
]