1. 程式人生 > 其它 >reduce 一個 笛卡爾積_dfs在笛卡爾積中的應用

reduce 一個 笛卡爾積_dfs在笛卡爾積中的應用

技術標籤:reduce 一個 笛卡爾積

在掘金看了一篇有關笛卡爾積實際應用的例子,剛敲完程式碼,順便總結一下。(文章程式碼都沒有進行邊界處理)

例如商品規格的排列組合,我們給出以下陣列:

  const productNames = ['iphone12', 'iphone12 Pro']
  const colors = ['white', 'black']
  const storages = ['64', '128', '256']

要得到結果為[['iphone12', 'white', '64'], ['iphone12', 'white', '128']....]的陣列(結果太長就不寫了),這很明顯是一個求n個集合笛卡爾積的問題。先貼一下dfs程式碼:

function getCartesianProduct(list) {
    const res = []
    dfs(list, 0, [], res)
    return res
}
/**
 * @description: 輔助遞迴函式
 * @param {array} list - 原陣列
 * @param {number} idx - 初始層級
 * @param {array} path - 遞迴經過的路徑,滿足條件後新增到res中
 * @param {array} res 最終返回的結果
 * @return void
 */
function dfs(list, idx, path, res) {
    if(path.length >= list.length) {
        res.push(path.slice())
        return
    }
    for(let i=0; i<list[idx].length; ++i) {
        path.push(list[idx][i])
        dfs(list, idx+1, path, res)
        path.pop()
    }
}

用遞迴寫法程式碼相對簡單,但是不容易理解。

用迴圈來寫,更符合我們直觀感受。例如求M×N×O的笛卡爾積,可以先求M×N的笛卡爾積,結果再跟O相乘,這樣更直觀。下面使用JavaScript中Array.prototype.reduce()方法改寫:

function getCartesianProduct(list) {

    return list.reduce((total, cur) => {
        const res = []

        for(let i=0; i<total.length; ++i) {
            for(let j=0; j<cur.length; ++j) {
                const flag = Array.isArray(total[i])
                //total[i]的值為陣列就展開
                if(flag){
                    res.push([...total[i], cur[j]])
                } else{
                    res.push([total[i], cur[j]])
                }
            }
        }
        return res
    })
}

參考連結:

前端電商 sku 的全排列演算法很難嗎?學會這個套路,徹底掌握排列組合。​juejin.im