2015-10-14 77 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)) 
]