多個數組的組合排序算法

一,聊騷:前端

我是一個喜歡直奔主題的人,不喜歡把時間浪費到廢話上,由於這也是在浪費讀者到時間,那爲何我今天一反常態,要說點聊騷的話呢?vue

原因是這樣的,做爲一個自學成才(其實尚未成才)的前端人員來講,前端之路是多麼的坎坷,面對大量的前端知識,面對如雨後春筍般的前端框架的興起,面對nodejs在前端與後端之間的鏈接的應用,node

此時的前端不再是幾年前的那個前端了,有太多的框架要去學,有太多的前端知識要去研究,學習,這樣不免會讓人失去方向,學的東西也很雜,爲了適應如今的對前端人員的要求,你就不得不撒開網去react

探索,致使的結果就是,你好像什麼都接觸過,感受什麼都懂,可是若是要你說出一個因此然來,好像又什麼都不懂,這纔是前端學習最可怕的,浮於表面,沒有真正深刻了解其中的原理,有人會說,如今的技術學習曲線那麼陡,要學的知識那麼多,哪有那麼多時間去學呢?webpack

回答這個問題,我得先說,我失業了,就如同我前面說的同樣,我只是浮於表面,沒有真正沉下去,那怎麼才能學好技術呢?根據牛人的指導,大體是在技術選型上,選擇適合本身的,好比說前端框架,angularjs,reactjs,backbonejs,vuejs等等,選擇一個本身以爲比較好上手的,而後搭配一個打包工具,好比webpack,gulp,grunt等等,多去深刻理解它的實現原理,編寫的思想,總之,多看,angularjs

多寫(這纔是重點),多研究,而後把本身的心得感悟,以筆記或者博客的形式記錄下來,讓牛人們幫你噴噴,這樣既能夠加深印象,還能夠和牛人一塊兒學習,算了,不說了,這實際上是寫給我看的。web

二,正題:算法

言歸正傳,今天咱們要講的是一個什麼命題呢?gulp

命題:多維數組的排列組合 或 多個數組之間的排列組合後端

命題場景:

如今有一批手機,其中顏色有['白色','黑色','金色'];內存大小有['16G','32G','64G'],版本有['移動','聯通','電信'],要求寫一個算法,實現[['白色','16G','移動'], ['白色','16G','聯通'] ...]這樣的組合,擴張,若是後面還有參數,好比再加一個['國行','港版'],不改程序同樣能夠執行!

不知道要實現的需求你們聽懂了沒有,下面我會一步步實現,教你們怎麼寫:

最後獲得的結果是一個數組裏麪包含若干個數組,看着挺複雜的,咱們先實現一個簡化版的,數組裏面不是數組,而是字符串鏈接的結果,嗯,先一步步來吧:

第一步,想一想經過什麼技術來實現,你看這數組之間不斷的重組,很容易想到用回調函數,一遍一遍的執行,大體知道用什麼技術,接下來就是寫思路了,看看下面:

// 執行組合排列的函數
    function doExchange(arr){ } //執行
    var arr = [['a', 'b', 'c'], [1, 2, 3], ['x', 'y', 'z']]; var arr1 = [['a','b','c']]; //doExchange(arr);
    console.log(doExchange(arr));

 

吶,咱們建一個函數doExchange(),表示咱們執行排序的主函數,而後當執行arr的時候,輸出['a1x','a1y' ...]這樣的結果,若是是arr1呢?咱們須要輸出['a','b','c'],這好理解哈,如今的重點就是這個主函數了,下面主要講主函數的實現過程

// 執行組合排列的函數
    function doExchange(arr){ var len = arr.length; // 當數組大於等於2個的時候
        if(len >= 2){ }else{ return arr[0]; } }

 

咱們的思路是,當參數裏面的數組長度大於2個,好比2個,3個或更多,就執行咱們的組合代碼,不然只有一個,就直接輸出來唄

若是是大於2個呢?咱們的思路是先進行第一個和第二個的合併,網上有一種實現方式是,用多層for循環來嵌套,最終獲得組合的值,這種估計你們也能感受到,兩三個還能夠,多了就呵呵了,這裏只是提一下,由於前兩個比較好獲取,合併以後呢,就至關因而

2個數組合併成一個數組,而後這個數組再放倒參數數組中第一個位置,把原來前兩個去掉,至關因而用這個數組替換前兩個,沒聽懂哈,不要緊,咱們直接看代碼:

if(len >= 2){ // 第一個數組的長度
            var len1 = arr[0].length; // 第二個數組的長度
            var len2 = arr[1].length; // 2個數組產生的組合數
            var lenBoth = len1 * len2; // 申明一個新數組,作數據暫存
            var items = new Array(lenBoth); // 申明新數組的索引
            var index = 0; // 2層嵌套循環,將組合放到新數組中
            for(var i=0; i<len1; i++){ for(var j=0; j<len2; j++){ items[index] = arr[0][i] + arr[1][j]; index++; } } }

 

吶,這裏咱們先獲取第一個和第二個數組的長度,而後計算出它們有多少種組合方式,而後新建一個暫存的數組,用來存咱們組合獲得的結果,後面就是用雙層循環,作字符串鏈接,放到暫存數組中,沒什麼好說的

咱們的到了前兩個的組合結果,依據咱們的思路,是要把它和原來數組合併成一個新數組

// 第一個數組的長度
            var len1 = arr[0].length; // 第二個數組的長度
            var len2 = arr[1].length; // 2個數組產生的組合數
            var lenBoth = len1 * len2; // 申明一個新數組,作數據暫存
            var items = new Array(lenBoth); // 申明新數組的索引
            var index = 0; // 2層嵌套循環,將組合放到新數組中
            for(var i=0; i<len1; i++){ for(var j=0; j<len2; j++){ items[index] = arr[0][i] + arr[1][j]; index++; } } // 將新組合的數組併到原數組中
            var newArr = new Array(len -1); for(var i=2;i<arr.length;i++){ newArr[i-1] = arr[i]; } newArr[0] = items;

 

總體的思路就是這樣,獲得的新數組就是剩下的未組合的數組了,到這裏你們應該就豁然開朗了,而後使用遞歸再次調用這個過程,這樣不斷組合成新數組,那這個新數組當參數時,若是數組的長度等於1了,就說明組合完了,就會執行後面的else語句,輸出出來。

總體代碼貼出來感覺一下:

// 執行組合排列的函數
    function doExchange(arr){ var len = arr.length; // 當數組大於等於2個的時候
        if(len >= 2){ // 第一個數組的長度
            var len1 = arr[0].length; // 第二個數組的長度
            var len2 = arr[1].length; // 2個數組產生的組合數
            var lenBoth = len1 * len2; // 申明一個新數組,作數據暫存
            var items = new Array(lenBoth); // 申明新數組的索引
            var index = 0; // 2層嵌套循環,將組合放到新數組中
            for(var i=0; i<len1; i++){ for(var j=0; j<len2; j++){ items[index] = arr[0][i] + arr[1][j]; index++; } } // 將新組合的數組併到原數組中
            var newArr = new Array(len -1); for(var i=2;i<arr.length;i++){ newArr[i-1] = arr[i]; } newArr[0] = items; // 執行回調
            return doExchange(newArr); }else{ return arr[0]; } } //執行
    var arr = [['a', 'b', 'c'], [1, 2, 3], ['x', 'y', 'z']]; var arr1 = [['a','b','c']]; //doExchange(arr);
    console.log(doExchange(arr));

執行arr和arr1的結果給你們截個圖吧:

咱們簡化版的組合算是完成了,可能也會有相似的需求,可是咱們今天要講的不是這樣的需求,而是裏面的每個組合要是一個數組,這個怎麼實現呢?

突破點應該就在字符串鏈接那塊了,原來是用的字符串鏈接,若是咱們改爲數組鏈接,不就好了嗎?試試:

for(var i=0; i<len1; i++){ for(var j=0; j<len2; j++){ if(arr[0][i] instanceof Array){ items[index] = arr[0][i].concat(arr[1][j]); }else{ items[index] = [arr[0][i]].concat(arr[1][j]); } index++; } }

 

其餘地方都沒有改,就只是改了這裏,可是這裏第一次是要作數組判斷的,由於剛開始是字符串,要轉換成數組才能鏈接,這裏注意一下,最終的代碼以下:

function doExchange(arr){ var len = arr.length; // 當數組大於等於2個的時候
        if(len >= 2){ // 第一個數組的長度
            var len1 = arr[0].length; // 第二個數組的長度
            var len2 = arr[1].length; // 2個數組產生的組合數
            var lenBoth = len1 * len2; // 申明一個新數組
            var items = new Array(lenBoth); // 申明新數組的索引
            var index = 0; for(var i=0; i<len1; i++){ for(var j=0; j<len2; j++){ if(arr[0][i] instanceof Array){ items[index] = arr[0][i].concat(arr[1][j]); }else{ items[index] = [arr[0][i]].concat(arr[1][j]); } index++; } } var newArr = new Array(len -1); for(var i=2;i<arr.length;i++){ newArr[i-1] = arr[i]; } newArr[0] = items; return doExchange(newArr); }else{ return arr[0]; } } //     var arr = [['a', 'b', 'c'], [1, 2, 3], ['x', 'y', 'z'],['手機']]; var arr1 = [['a','b','c']]; console.log(doExchange(arr));

 

獲得的結果:

我後面又加了一個手機,一樣是能夠實現的,到這裏就算死寫完了。

 

三,總結:

給個總結吧,這個算法剛開始想一想,感受挺複雜的,這麼多數組要排列組合,可是咱們將它化繁爲簡,好比說就當只有2個數組的組合,是否是就簡單多了,這個實現了,而後考慮多組的,這樣世界就清靜了!仍是那句話,仍是多寫吧!

歡迎轉載,原創不易,轉載時請註明出處,謝謝!

相關文章
相關標籤/搜索