Skip to content

Instantly share code, notes, and snippets.

@coodoo
Created August 17, 2021 22:32
Show Gist options
  • Save coodoo/8ae9a16a70432142bafd4abaf3560661 to your computer and use it in GitHub Desktop.
Save coodoo/8ae9a16a70432142bafd4abaf3560661 to your computer and use it in GitHub Desktop.
permutation in js with reducer
let arr = [
['a1', 'a2'],
['b1', 'b2', 'b3']
]
let result = arr.reduce(
// -----------
// 最外層 reduce 會依序遍歷
// ['a1', 'a2'] 與 ['b1', 'b2', 'b3']
(xs, cs) => {
// --------
// xs 是 accumulator 累計每輪運算的結果
// cs 是當前這輪的數值,例如第一輪是 ['a1', 'a2']
return cs.flatMap(
// -----------
// 第一輪時遍歷 cs=['a1', 'a2']
//
// 如果這裏用 map() 則產出格將為多層陣列,將來不好用,例如:
//
// [ [ [ 'a1' ] ], [ [ 'a2' ] ] ]
//
// 改用 flatMap() 則會剝皮到只剩一層,方便後續使用,例如
//
// [ [ 'a1' ], [ 'a2' ] ]
c => xs.map(x => [...x, c]))
// ----------------------------
// 這裏取得 c = 'a1'
// 但接著啟動內部第二層 xs[] 的遍歷
// xs 是當初給入的 accumulator 初始值,內容為 [[]]
// 此處遍歷 xs[] 就是在走訪二維陣列內部那層 []
// 因此如果一開始沒給二維陣列 [[]],則這層 xs.map() 就無東西可走訪
// 整個運算就失敗了
//
// 當這層算完,會將 xs[] 的內容與 c 兩者透過 spread 語法(...) 組合在一起返還
// 也就是 [...x, c] 這段
// 第一輪時由於 xs=[[]] 內是空值因此組合後會得到 [['a1']]
// 第二輪時 xs=[['a1']] 組合後會得到 [['a1', 'b1']]
// -----------------------
// 最後看整體運算流程時的 input 與 output 內容
//
// # in
//
// { xs: [ [] ], cs: [ 'a1', 'a2' ] }
//
// # out
//
// [ [ 'a1' ], [ 'a2' ] ]
//
// # in
//
// { xs: [ [ 'a1' ], [ 'a2' ] ], cs: [ 'b1', 'b2' ] }
//
// # out
//
// [ [ 'a1', 'b1' ], [ 'a2', 'b1' ], [ 'a1', 'b2' ], [ 'a2', 'b2' ] ]
},
[[]]
// ----
// 這是 reduce(fn, accumulator) 中 accumulator 的部份
// 注意是給二維陣列
)
console.log(`result`, result)
// [
// [ 'a1', 'b1' ],
// [ 'a2', 'b1' ],
// [ 'a1', 'b2' ],
// [ 'a2', 'b2' ],
// [ 'a1', 'b3' ],
// [ 'a2', 'b3' ]
// ]
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment