js算法初窺06(算法模式03-函數式編程)

   在解釋什麼是函數式編程以前,咱們先要說下什麼是命令式編程,它們都屬於編程範式的一種。命令式編程其實就是一塊一塊的代碼,其中包括了咱們要執行的邏輯或者判斷或者一些運算。也就是循序漸進的一步一步完成咱們所須要的邏輯。而函數式編程則是相似於一個函數一個函數的調用。咱們來看代碼,更清晰的理解一下函數式編程與命令式編程的區別。html

//這是命令式
var printArray = function (array) {
    for (var i = 0; i < array.length; i++) {
        console.log(array[i])
    }
}
printArray([1,2,3,4,5]);
//函數式
var forEach = function (array,action) {
    for (var i = 0; i < array.length; i++) {
        action(array[i])
    }
}

var logItem = function (item) {
    console.log(item)
}

forEach([2,3,4,5,6],logItem)

  咱們先來看看上面的代碼作了什麼——「遍歷數組,而後打印數組的每一項」。在命令式編程中,咱們一步一步的完成了這句話。先遍歷數組,而後打印每一項元素。那麼咱們再來看函數式編程,咱們先聲明瞭兩個函數,一個是遍歷數組元素的forEach(這裏的action參數其實就是一個回調函數),一個是打印每一項的logItem。咱們把每一步驟的須要操做的邏輯都用函數來區分開,最後再調用函數來執行運算。react

  在有了ES6以後,咱們能夠更加方便的用函數式編程範式來編寫咱們的代碼,下面咱們再來看一個例子。es6

//找出數組中元素最小的值
//代碼十分簡單,咱們假設數組的第一個元素是最小的並賦值給minVal變量
//遍歷除第一項元素之外的全部數組內元素並與minVal比較,若是當前的minVal比array[i]還要大,那麼就把minVal替換成array[i];
//最後返回結果
var findMinValInArray = function (array) {
    var minVal = array[0];
    for (var i = 1; i < array.length; i++) {
        if(minVal > array[i]) {
            minVal = array[i];
        }
    }
    return minVal;
}
console.log(findMinValInArray([7,8,9,5,31,2]));
//那麼咱們其實能夠更簡單的實現上面的方法,好比Math.min以及解構操做符(...)
const _min = function (array) {
    return Math.min(...array);
}
console.log(_min([5,6,9,3,1]));
//咱們還能夠用ES6的箭頭函數,讓咱們的代碼更好看一些。
const min = arr => Math.min(...arr);
console.log(min([2,3,9,4,8]))

  上面代碼中Math.min是一個方法,返回參數中的最小值,參數能夠是無限個。那麼還有ES6的箭頭函數以及擴展運算符(...)。這裏不作詳細的解釋,附上鍊接地址,你們能夠更爲詳細的知道什麼是箭頭函數以及擴展運算符。編程

  那麼,接下來咱們看看如何利用咱們前面已經學過的數組方法來讓咱們的代碼更加「函數式」。數組

//咱們先看一個命令式編程的例子
var daysOfWeek = [
    {name:"Monday",value:1},
    {name:"Tuesday",value:2},
    {name:"Wednesday",value:7},
]
var daysOfWeekValues_ = [];
for (var i = 0; i < daysOfWeek.length; i++) {
    daysOfWeekValues_.push(daysOfWeek[i].value);
}

//再來看看函數式編程的樣子
var daysOfWeekValues = daysOfWeek.map(function (day) {
    //這個day其實就是數組中的每一項,具體能夠去我前面的文章查看map的參數
    return day.value;
})
console.log(daysOfWeekValues);

//咱們還可使用filter來過濾一個數組的值。
//好比:
//命令式
var positiveNumbers_ = function (array) {
    var positive = [];
    for (var i = 0; i < array.length; i++) {
        if(array[i] >= 0) {
            positive.push(array[i]);
        }
    }

    return positive;
}
console.log(positiveNumbers_([-1,2,1,-2]));
//函數式
var positiveNumbers = function (array) {
    return array.filter(function (num) {
        return num >= 0;
    })
}

console.log(positiveNumbers([1,2,-1,-2,-5]));

//咱們再來看看reduce函數
//命令式
var sumValues = function (array) {
    var total = array[0];
    for (var i = 1; i < array.length; i++) {
        total += array[i];
    }
    return total;
}
console.log(sumValues([1,2,3,4,5]));
//函數式
var sum_ = function (array) {
    return array.reduce(function (a,b) {
        return a + b;
    })
}

console.log(sum_([1,2,3,4,5]))
//咱們還能夠用ES6的方法改進一下
var sum = arr => arr.reduce((a,b) => a + b);
console.log(sum([1,2,3,4,5]))

  上面咱們看了一些函數式編程的例子,代碼都不復雜,很容易理解。因此就沒作詳細的註釋。那麼咱們下面再看最後一個有趣的例子。函數式編程

//咱們來用命令式編程實現一個二維數組合併爲一維數組的方法
var mergeArrays_ = function (arrays) {
    var count = arrays.length,
    newArray = [],
    k = 0;

    for (var i = 0; i < count; i++) {
        for (var j = 0; j < arrays[i].length; j++) {
            newArray[k++] = arrays[i][j];
        }
    }
    return newArray;
}

console.log(mergeArrays_([[1,2,3],[4,5],[6]]));

//咱們最後再看看函數式的寫法
var mergeArraysConcat = function (arrays) {
    return arrays.reduce(function (p,n) {
        return p.concat(n);
    })
};
console.log(mergeArraysConcat([[1,2,3],[4,5],[6],[7]]))

//咱們再來看看牛逼的方法
const mergeArrays = (...arrays) => [].concat(...arrays);
console.log(mergeArrays([1,2,3],[4,5],[6],[7],[8]));
//這一行代碼須要解釋下。咱們來看看(...arrays)會變成什麼
console.log(...[[1,2,3],[4,5],[6],[7],[8]])//一個一個單獨的數組
//而後咱們再用一個空數組去合併參數中的每個單獨的數組就能夠了

  到這裏咱們函數式編程的簡單講解就結束了,上面的內容其實不過萬分之一,但願能讓你們對代碼的編寫打開了另外一扇窗戶,其實函數式編程在咱們的實際工做中也是極爲有用的。但願你們能夠認真對待和學習,最後,附上一個能夠學習函數式編程的網址:http://reactivex.io/learnrx/。這是一個外國的練習網站,只要會簡單的英語看下來應該是沒有問題的。函數

  

  最後,因爲本人水平有限,能力與大神仍相差甚遠,如有錯誤或不明之處,還望你們不吝賜教指正。很是感謝!學習

相關文章
相關標籤/搜索