ããããããã©ã³ã¹ãã¥ãŒãµãŒãã«ã€ããŠèããããšããããŸãããããã§ãJavaScriptã®éçºã«äœ¿çšããªãå Žåã¯ã仿¥ãããã©ã³ã¹ãã¥ãŒãµãŒãšã¯ããšãäœ¿çšæ¹æ³ããšãã質åã«å¯ŸããçããèŠã€ããæ©äŒããããŸãã ããã«ããããããžã§ã¯ãã§ããããå¿
èŠãã©ãããçè§£ã§ããããã«ãªããå¿
èŠã«å¿ããŠãããã®äœ¿çšãéå§ããã®ã«åœ¹ç«ã¡ãŸãã

ããã¯ãããŸãå€ãã®ã¡ã¢ãªãæ¶è²»ããã«ãã€ãã©ã€ã³ããªã³ã¯ããã®ã«é©ããããŒã¿å€æãæ§ç¯ããããã«èšèšãããã³ãŒããã©ã®ããã«æžããã«ã€ããŠã§ãã ãã©ã³ã¹ãã¥ãŒãµã®æŠå¿µãé©åã«çè§£ããããã«ãããŒã¿ãæãç³ãããã®åçŽãªã¡ã«ããºã ãæžéæ©ããŸãã¯æ©èœããå§ããŸãã
æžéæ©
ã¬ãã¥ãŒãµãŒã¯ãã¹ãã¬ãŒãžãªããžã§ã¯ããšç¹å®ã®ãªããžã§ã¯ãèŠçŽ ãå
¥åãšããŠåãå
¥ãããã®èŠçŽ ããã©ã€ãã«é
眮ããæ©èœã§ãã ããšãã°ãã¬ãã¥ãŒãµãŒã¯æ¬¡ã®ãšããã§ãã
(acc, val) => acc.concat([val])
ã 転éããããã©ã€ããé
å
[1, 2, 3]
ã§ãèŠçŽ ãæ°å
4
å Žåãé
å
[1, 2, 3, 4]
ãè¿ããŸãã
const acc = [1, 2, 3]; const val = 4; const reducer = (acc, val) => acc.concat([val]); reducer(acc, val)
ãã®å Žåããªãã¥ãŒãµãŒã¯ãæž¡ãããèŠçŽ ã®ãªã¹ããšãŠãããèŠçŽ ãé£çµããçµæãè¿ããŸãã
åæ§ã®å¥ã®ã¬ãã¥ãŒãµãŒããããŸãïŒ
(acc, val) => acc.add(val)
ã ãã®ãªããžã§ã¯ããè¿ã
.add()
ã¡ãœãããæã€ãªããžã§ã¯ãã«é©ããŠããŸãïŒ
Set.prototype.addïŒïŒãªã© ïŒã ã¬ãã¥ãŒãµãŒã¯ãã¡ãœããã䜿çšããŠãæž¡ãããèŠçŽ ããã©ã€ãã«è¿œå ããŸãã
add()
ãã©ã€ãã
add()
ãŸãã
const acc = new Set([1, 2, 3]); const val = 4; const reducer = (acc, val) => acc.add(val); reducer(acc, val)
é£çµã¬ãã¥ãŒãµãŒã䜿çšããŠå埩å¯èœãªãªããžã§ã¯ãããé
åãäœæãã颿°ã次ã«ç€ºããŸãã
const toArray = iterable => { const reducer = (acc, val) => acc.concat([val]); const seed = []; let accumulation = seed; for (value of iterable) { accumulation = reducer(accumulation, value); } return accumulation; } toArray([1, 2, 3])
æ®éçãªéå
颿°ãååŸããããšã«ããã
reducer
倿°ãš
seed
倿°ãæ°ãã颿°ã®ãã©ã¡ãŒã¿ãŒã«ããããšãã§ããŸãïŒèæ
®ãããã°ããã®åŒæ°ãšã®é¡äŒŒã«ãããåŒæ°
iterable
åãå
¥ããŸãïŒã
const reduce = (iterable, reducer, seed) => { let accumulation = seed; for (const value of iterable) { accumulation = reducer(accumulation, value); return accumulation; } reduce([1, 2, 3], (acc, val) => acc.concat([val]), [])
JavaScriptã¯ãæåã®ãã©ã¡ãŒã¿ãŒããªãã¥ãŒãµãŒã§ãã
reduce
ãããªé¢æ°ã®èšè¿°ã«é¢ããåæã«åãã£ãŠé²åããŠããŸãã ãã®é¢æ°ã
JavaScriptAllongéã¹ã¿ã€ã«ã§æžãæãããšã次ã®ããã«ãªããŸãã
const reduceWith = (reducer, seed, iterable) => { let accumulation = seed; for (const value of iterable) { accumulation = reducer(accumulation, value); } return accumulation; } reduce([1, 2, 3], (acc, val) => acc.concat([val]), []) //=> [1, 2, 3] // : reduceWith((acc, val) => acc.concat([val]), [], [1, 2, 3]) //=> [1, 2, 3]
JavaScriptã®é
åã«ã¯ãçµã¿èŸŒã¿ã®
.reduce
ã¡ãœããããããŸãã ãã®ã¡ãœããã¯ãäžèšã®
reduce
ããã³
reduceWith
颿°ãšãŸã£ããåãããã«åäœããŸãã
[1, 2, 3].reduce((acc, val) => acc.concat([val]), [])
ããã§ã颿°
(acc, val) => acc.concat([val])
ã¯äžèŠãªã¡ã¢ãªè² è·ãäœæãããããæ¬¡ã®ãããªãªãã¥ãŒãµãŒã«çœ®ãæããããšãã§ããŸãã
(acc, val) => { acc.push(val); return acc; }
(acc, val) => { acc.push(val); return acc; }
(acc, val) => { acc.push(val); return acc; }
圢åŒ
(acc, val) => (acc.push(val), acc)
ã¬ã³ãŒãã¯ãã»ãã³ãã£ãã¯ã®èгç¹ããã¯ããè¯ãèŠããŸãããã³ã³ãæŒç®åã¯ããã®äœ¿çšã®æ©èœã«æ
£ããŠããªãäººãæ··ä¹±ãããå¯èœæ§ãããããšã«æ³šæããŠãã ããã ããã¯éåžžãå®çšŒåã³ãŒãã§ã¯é¿ããã®ãæåã§ãã
ãããã®å Žåã§ããèŠçŽ ãé
åã«åéããã¬ãã¥ãŒãµãŒãååŸããŸãã ååãä»ããŠã
reduceWith
颿°ãæž¡ãããšããŸãã
const arrayOf = (acc, val) => { acc.push(val); return acc; }; reduceWith(arrayOf, [], [1, 2, 3])
å¥ã®æžéæ©ããããŸãã
const sumOf = (acc, val) => acc + val; reduceWith(sumOf, 0, [1, 2, 3])
ããã¿ã€ãã®å埩å¯èœãªãªããžã§ã¯ãïŒé
åãªã©ïŒãå¥ã®ã¿ã€ãã®ãªããžã§ã¯ãïŒæ°å€ãªã©ïŒã«çž®å°ããã¬ãã¥ãŒãµãŒãäœæã§ããŸãã
æžéæ©ã食ã
JavaScriptã䜿çšãããšãä»ã®é¢æ°ãè¿ã颿°ãç°¡åã«äœæã§ããŸãã ããšãã°ãããã¯ã¬ãã¥ãŒãµãŒãäœæã§ãã颿°ã§ãã
const joinedWith = separator => (acc, val) => acc == '' ? val : `${acc}${separator}${val}`; reduceWith(joinedWith(', '), '', [1, 2, 3])
ããã«ãJSã§ã¯ãä»ã®é¢æ°ãåŒæ°ãšããŠåã颿°ãäœæããããšã¯å®å
šã«èªç¶ã§ãã
ãã³ã¬ãŒã¿ã¯ã颿°ãåŒæ°ãšããŠåãããã®åŒæ°ã«æå³çã«é¢é£ä»ããããŠããå¥ã®é¢æ°ãè¿ã颿°ã§ãã ããšãã°ããã®é¢æ°ã¯ã颿°åããã°ã©ãã³ã°ã®èšèªã話ãå Žåããã€ããªã®2ã€ã®åŒæ°ãæã€é¢æ°ãåãã2çªç®ã®åŒæ°ã«1ã远å ããŠè£
食ããŸãã
const incrementSecondArgument = binaryFn => (x, y) => binaryFn(x, y + 1); const power = (base, exponent) => base ** exponent; const higherPower = incrementSecondArgument(power); power(2, 3)
ãã®äŸã§ã¯ã
higherPower
颿°ã¯
exponent
åäœã远å ããããšã§ä¿®é£Ÿããã
exponent
ã§ãã ãããã£ãŠã
higherPower(2,3)
ãåŒã³åºããšã
power(2,4)
ãšåãçµæãåŸãããŸãã ç§ãã¡ã¯ãã§ã«åæ§ã®é¢æ°ã䜿çšããŠããŸãããã¬ãã¥ãŒãµãŒããã€ããªé¢æ°ã§ãã 圌ãã¯è£
食ããããšãã§ããŸãã
reduceWith(incrementSecondArgument(arrayOf), [], [1, 2, 3])
ãããã³ã°é¢æ°
ãããã³ã°çšã®é¢æ°ãäœæããŸããããã®é¢æ°ã¯ãå埩å¯èœãªãªããžã§ã¯ããååŸããããããã®å€ã1ã€ãã€å¢ãããŠå€ãåŠçããçµæãè¿ããŸãã JSã§ããã°ã©ã ãéçºãããšããç§ãã¡ã¯åžžã«ãããã³ã°ã«é ŒããŸããããã¡ããããã®ã¡ã«ããºã ãå®è£
ãã颿°ã¯éåžžãèŠçŽ ã1å¢å ããæ°å€é
åã®ã³ããŒãäœæããããããããã«å€§ãããšäºæ³ãããŸãã
incrementSecondArgument
颿°ãããäžåºŠèŠãŠã¿ãŸãããã
const incrementSecondArgument = binaryFn => (x, y) => binaryFn(x, y + 1)
æžéæ©ãè£
食ããããã«äœ¿çšãããããããé©åãªååãä»ããŸãã
const incrementValue = reducer => (acc, val) => reducer(acc, val + 1)
ããã§ãã³ãŒããèªã¿åããšãã«ã
incrementValue
ãã¬ãã¥ãŒãµãŒãåŒæ°ãšããŠåãåããæž¡ãããèŠçŽ ãåŠçããåã«ã¬ãã¥ãŒãµãŒã远å ããå¥ã®ã¬ãã¥ãŒãµãŒãè¿ãããšãããã«ããã
incrementValue
ã ãå¢åãã®ããžãã¯ããã©ã¡ãŒã¿ãŒã«å
¥ããããšãã§ããŸãã
const map = fn => reducer => (acc, val) => reducer(acc, fn(val)); const incrementValue = map(x => x + 1); reduceWith(incrementValue(arrayOf), [], [1, 2, 3])
ããã¯ãã¹ãŠã颿°ãåŒæ°ãšããŠåãåãã颿°ãåŒæ°ãšããŠåãåãä»ã®é¢æ°ãè¿ã颿°ã«æ
£ããŠããªã人ã«ã¯çããããã«èŠããŸããã
map(x => x + 1)
æ§é ãã©ãã«ã§ãé
眮ã§ããŸããããã§
incrementValue
ã䜿çš
incrementValue
ã ãããã£ãŠã次ã®ããã«æžãããšãã§ããŸãã
reduceWith(map(x => x + 1)(arrayOf), [], [1, 2, 3])
ãŸãã
map
ãã³ã¬ãŒã¿ã¯ä»»æã®ã¬ãžã¥ãŒãµãŒããã³ã¬ãŒãã§ãããããæ°å€ãã€ã³ã¯ãªã¡ã³ãããçµæãçµã¿åãããŠæååã圢æããããåèšãããããããšãã§ããŸãã
reduceWith(map(x => x + 1)(joinedWith('.')), '', [1, 2, 3]) //=> "2.3.4" reduceWith(map(x => x + 1)(sumOf), 0, [1, 2, 3]) //=> 9
äžèšã®ææ³ã䜿çšããŠã1ãã10ãŸã§ã®æ°ã®å¹³æ¹åãèŠã€ããŠãã ããã
const squares = map(x => power(x, 2)); const one2ten = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]; reduceWith(squares(sumOf), 0, one2ten)
ã芧ã®ãšãããæåããŸããã æ¬¡ã«é²ã¿ãŸããã-ãã£ã«ã¿ã«ã€ããŠè©±ããŸãããã
ãã£ã«ã¿ãŒ
æåã®æžéæ©ã«æ»ããŸãã
const arrayOf = (acc, val) => { acc.push(val); return acc; }; reduceWith(arrayOf, 0, one2ten)
5ãè¶
ããæ°ã®ã¿ãååŸããå Žåã¯ã©ããªããŸããïŒ ç°¡åã«ã
const bigUns = (acc, val) => { if (val > 5 ) { acc.push(val); } return acc; }; reduceWith(bigUns, [], one2ten)
åœç¶ã®ããšãªããã5ä¹ãè¶
ããæ°ã®é
åãååŸããããã«ããã§ã«ããã£ãŠãããã¹ãŠã®ãã®ãçµã¿åãããããšãã§ããŸãã
reduceWith(squares(bigUns), [], one2ten)
ããããããã§å€æããã®ã¯ç§ãã¡ãå¿
èŠãšãããã®ã§ã¯ãããŸããã åºåã¯ã2ä¹ã5ãè¶
ããæ°å€ã§ã¯ãªãã2ä¹ã5ãè¶
ããæ°å€ã§ãã çªå·ã¯ãçªå·ã§ã¯ãªããå¹³æ¹ããåã«éžæããªããã°ãªããŸããã ã·ã¹ãã ã®ãã®åäœãå®çŸããããšã¯ããã»ã©é£ãããããŸããã ããã§ã®äžçªäžã®è¡ã¯ãæ°å€ã®ãã£ã«ã¿ãªã³ã°ãæ
åœãããã³ã¬ãŒã¿ãŒãç§ãã¡ãå©ããŠãããã®ã§ãããã䜿ã£ãŠã¬ãã¥ãŒãµãŒã食ãããšãã§ããŸãã
reduceWith(squares(arrayOf), [], one2ten)
bigUnsOf
颿°
bigUnsOf
éåžžã«å
·äœçã§ãã ããã§ã¯ã
map
ãšåãããšãè¡ã
map
ãã€ãŸããè¿°èªé¢æ°ãæœåºãããããåŒæ°ã«ããŸãã
reduceWith(squares(arrayOf), [], one2ten) //=> [1, 4, 9, 16, 25, 36, 49, 64, 81, 100] const filter = fn => reducer => (acc, val) => fn(val) ? reducer(acc, val) : acc; reduceWith(filter(x => x > 5)(squares(arrayOf)), [], one2ten) //=> [36, 49, 64, 81, 100]
ãã¡ããããã£ã«ã¿ãŒã¯ã©ãã§ãããŸããŸããã ãããã«ååãä»ããŠç¹°ãè¿ã䜿çšããããå¿å颿°ã䜿çšãããã§ããŸãã
reduceWith(filter(x => x % 2 === 1)(arrayOf), [], one2ten)
ãã£ã«ã¿ãŒã䜿çšããŠã1ãã10ãŸã§ã®å¥æ°ã®å¹³æ¹åãèŠã€ããŸãã
reduceWith(filter(x => x % 2 === 1)(squares(sumOf)), 0, one2ten) //=> 165
ãã©ã³ã¹ãã©ãŒããŒãšæ§æ
ããã©ã³ã¹ãã©ãŒããŒããšããçšèªã¯ãä»ã®ããã°ã©ãã³ã°èšèªããJavaScriptã«æ¥ãŸããã ããã¯ãåŒæ°ãåãããããå¥ã®ãã®ã«å€æãã颿°ã®ååã§ãã äžèšã®ããã³ã¬ãŒã¿ããšåŒã°ããã®ã¯ããã©ã³ã¹ã®ç¹æ®ãªã±ãŒã¹ã§ãã ãããã£ãŠããããªãã¥ãŒãµãŒãå¥ã®ãªãã¥ãŒãµãŒãšãã倿颿°ã«é¢ãã話ãã©ããã§äŒã£ãå Žåããªãã¥ãŒãµãŒããè£
食ãããåãæ©èœã«ã€ããŠè©±ããŠããããšã¯æããã§ããããããã³ã°ããã£ã«ã¿ãªã³ã°ãªã©ã®è¿œå æ©èœã远å ããŸãã
å
ã»ã©èª¬æãããããã³ã°é¢æ°ãšãã£ã«ã¿ãŒããã©ã³ã¹ãã©ãŒããŒã§ãã ãã®ããã°ã©ãã³ã°ãã¿ãŒã³ã®ã³ã³ããã¹ãã§ã¯ããã©ã³ã¹ãã©ãŒããŒã®æãéèŠãªç¹æ§ã¯ãæ§æã䜿çšããŠæ°ãããã©ã³ã¹ãã©ãŒããŒãäœæããããšã§ãã ããã§ã¯ãããæç¢ºã«ããããã«ãå
¥åæã«éä¿¡ãããä»»æã®2ã€ã®é¢æ°ã®æ§æãæäŸãã颿°ã
const plusFive = x => x + 5; const divideByTwo = x => x / 2; plusFive(3)
ãã©ã³ã¹ãã©ãŒããŒã¯æ§æã䜿çšããŠæ°ãããã©ã³ã¹ãã©ãŒããŒãäœæããŸãã
compose2
ã«é©çšããå Žåãããã¯ã©ãããæå³ã§ããïŒ ããã¯ã圌女ã«ä»»æã®2ã€ã®ãã©ã³ã¹ãã©ãŒããŒãäžãããšãæžéæ©ã倿ããæ°ãããã©ã³ã¹ãã©ãŒããŒãååŸããããšãæå³ããŸãã ãããã£ãŠã以äžãåŸãããŸãã
const squaresOfTheOddNumbers = compose2( filter(x => x % 2 === 1), squares )
squaresOfTheOddNumbers
ãšããååã§é ãããŠããã®ã¯ã
compose2
颿°ããã£ã«ã¿ãŒãšãããã³ã°é¢æ°ã«é©çšããããšã§äœæãããã©ã³ã¹ãã©ãŒããŒã§ãã
ãã³ã¬ãŒã¿ãäœæããæ©äŒãã§ããã®ã§ãé«åºŠãªæ¥ç¶æ§ã«ãã£ãŠåºå¥ãããè€éãªã³ãŒãããéåžžã«ç¹æ®ãªå°ããªãããã¯ã«åè§£ããŸãã
ãã©ã³ã¹æ§æ
compose2
颿°ãã©ã®ããã«æ©èœããããç¥ã£ãŠãã
compose2
ã2ã€ã®é¢æ°ã®åæãååŸã§ããŸããä»»æã®æ°ã®é¢æ°ã®åæãå¿
èŠãªå Žåã®å¯ŸåŠæ¹æ³ãèããŸãã çãã¯ç³ã¿èŸŒã¿ã§ãã
compose2
ãæžãçŽãã
compositionOf
ãã©ã³ã¹ãã©ãŒããŒãäœæããŸãã
const compositionOf = (acc, val) => (...args) => val(acc(...args))
ããã§ãåŒæ°ã®çž®å°ãšããŠä»»æã®æ°ã®é¢æ°ã®åæãååŸããããã«ãåæé¢æ°ã
compose
ã§ããŸãã
const compose = (...fns) => reduceWith(compositionOf, x => x, fns)
ã ãããç§ãã¡ã¯æãè峿·±ãããšã«ãªããŸãã
倿åš
次ã®ãšã³ããªãæ€èšããŠãã ããã
reduceWith(squaresOfTheOddNumbers(sumOf), 0, one2ten)
ããã§ã¯4ã€ã®èŠçŽ ãåºå¥ã§ããŸãã æžéæ©çšã®ãã©ã³ã¹ãã©ãŒããŒïŒãã©ã³ã¹ãã©ãŒããŒã®æ§æïŒãåæå€ïŒãã©ã€ãïŒããã³å埩å¯èœãªããžã§ã¯ãã ãã©ã³ã¹ãã©ãŒããŒãã¬ãã¥ãŒãµãŒããã©ã€ããå埩å¯èœãªãªããžã§ã¯ããå¥ã
ã®ãã©ã¡ãŒã¿ãŒã«å
¥ãããšã次ã®ããã«ãªããŸãã
const transduce = (transformer, reducer, seed, iterable) => { const transformedReducer = transformer(reducer); let accumulation = seed; for (const value of iterable) { accumulation = transformedReducer(accumulation, value); } return accumulation; } transduce(squaresOfTheOddNumbers, sumOf, 0, one2ten)
ããã€ãã®ããã°ã©ãã³ã°èšèªã§ã¯ã倿°ãŸãã¯ãã©ã¡ãŒã¿ãŒã®é·ãååãæžãããããšãã匷ãèŠæãããããšã«æ³šæããŠãã ããã ãã®çµæãããªãé·ãåå
transformer
xform
ãŸãã¯
xf
ççž®ãããŸãã ã¬ã³ãŒããïŒxfãreduceãseedãcolïŒããŸãã¯
xf((val, acc) => acc) -> (val, acc) => acc
ããã«èŠããé¡äŒŒã®æ§é ãèŠãŠé©ããªãã§ãã ããã ããã§ã¯çç¥ããã«å®è¡ã§ããŸãããçç£ã³ãŒãã§
xform
xf
ã
xform
ãããªåå
xform
ãŸã£ããåãå
¥ããããŸãã
ãããŠä»ãå®éã«ã¯ãããããã¹ãŠæžãããŠããããšã®ããã«ã ã¬ãã¥ãŒãµãŒã¯ã
.reduce â
ãªã©ã®ã¡ãœããã«æž¡ããã颿°ã§ããã¹ãã¬ãŒãžãªããžã§ã¯ããšå
¥åããŒã¿ãåãåããæ°ããããŒã¿ãé
眮ããããã©ã€ããè¿ããŸãã ãã©ã³ã¹ãã©ãŒããŒã¯ãæžéæ©ãå¥ã®æžéæ©ã«å€æããæ©èœã§ãã ãããŠããã©ã³ã¹ãã¥ãŒãµãŒïŒãã®ååã¯ããã©ã³ã¹ãã©ãŒããŒããšããªãã¥ãŒãµãŒããšããçšèªãçµã¿åãããçµæã§ããããã§ã¯ããã¬ãã¥ãŒãµãŒãšã¯äœã§ããïŒããšãã質åã«å¯Ÿããçãã§ãïŒç¹å®ã®å€ã§ã
倿åšãã³ãã¬ãŒãã®åªé
ãã¯ããã©ã³ã¹ã®æ§æãèªç¶ã«æ°ãããã©ã³ã¹ã®äœæã«ã€ãªãããšããäºå®ã«ãããŸãã ãã®çµæãå¿
èŠãªæ°ã®ãã©ã³ã¹ãã©ãŒããŒããã§ãŒã³ã§ããŸãã çµæã¯1ã€ã®å€æãããã¬ãã¥ãŒãµãŒã§ãããå埩ã³ã¬ã¯ã·ã§ã³ã1åã ãééããå¿
èŠããããããããã¯éåžžã«éèŠã§ãã ããŒã¿ã®äžéã³ããŒãäœæãããããããã«å¯ŸããŠè€æ°ã®ãã¹ãå®è¡ããå¿
èŠã¯ãããŸããã
ãã©ã³ã¹ãã¥ãŒãµãŒã¯ãClojureèšèªããJavaScriptã«ã¢ã¯ã»ã¹ããŸããããã芧ã®ãšãããJavaScriptã«å®å
šã«é©åããŠãããããå®è£
ã«ã¯èšèªã®æšæºæ©èœã§ååã§ãã
ã ããã誰ãããã©ã³ã¹ãã¥ãŒãµãŒãšã¯äœããç§ãã¡ã«å°ããããæ¬¡ã®ããã«çããããšãã§ããŸãïŒ
泚ïŒãã®ãã©ã°ã¡ã³ãã¯åŒ·èª¿è¡šç€ºããå¿
èŠããããŸãã
倿åšã¯åæã«é©ãã倿åšã§ãå埩å¯èœãªãªããžã§ã¯ããæãç³ãããã®æžéåšã«é©çšãããŸãã
åäœäžã®ãã©ã³ã¹ãã¥ãŒãµãŒ
äžèšã§ã¯ããã©ã³ã¹ãã¥ãŒãµãŒã®æ§ç¯ã«ã€ãªããã³ãŒãæçã調ã¹ãŸããã JSãšãã£ã¿ãŒã§æ¢ã«ããããåçŸããŠãã¹ãããŠããå¯èœæ§ã¯ååã«ãããŸãããããã§ã¯ã䟿å®äžãããããããããããã«ããã¹ãŠã®ã³ãŒãã1ãæã«éããŠããŸãã
const arrayOf = (acc, val) => { acc.push(val); return acc; }; const sumOf = (acc, val) => acc + val; const setOf = (acc, val) => acc.add(val); const map = fn => reducer => (acc, val) => reducer(acc, fn(val)); const filter = fn => reducer => (acc, val) => fn(val) ? reducer(acc, val) : acc; const compose = (...fns) => fns.reduce((acc, val) => (...args) => val(acc(...args)), x => x); const transduce = (transformer, reducer, seed, iterable) => { const transformedReducer = transformer(reducer); let accumulation = seed; for (const value of iterable) { accumulation = transformedReducer(accumulation, value); } return accumulation; }
ãã®äŸã¯ãé
åãæäœãããšãã«é垞䜿çšããããã¹ãŠã®ãã®ãã€ãŸã
.map
ã
.filter
ã
.reduce
ãããã«ãåŠçæžã¿ããŒã¿ã»ããã®è€æ°ã®ã³ããŒã®äœæã«é¢äžããªãæ§æã«é©ãããã©ã³ã¹ãã¥ãŒãµãŒããããŸãã å®éãå®éã®ãããžã§ã¯ãçšã«äœæããããã©ã³ã¹ãã¥ãŒãµãŒã¯ã
.find
ã¡ãœããã®æ©èœãåçŸãããªã©ãã¯ããã«å€ãã®ãŠãŒã¹
.find
æäŸããŸãã
transduse
颿°
transduse
å埩å¯èœãªã³ã¬ã¯ã·ã§ã³ã«è»¢éãããããã«èšèšãããŠããããšã«æ³šæããŠãã ãããããã«ãåæå€ïŒãã©ã€ãïŒãšãªãã¥ãŒãµãŒãæäŸããå¿
èŠããããŸãã ã»ãšãã©ã®å Žåãåæå€ãšãªãã¥ãŒãµãŒã¯ãåãã¿ã€ãã®ãã¹ãŠã®ã³ã¬ã¯ã·ã§ã³ã§åã颿°ã§ãã ããã¯ãåã©ã€ãã©ãªã«ãåœãŠã¯ãŸããŸãã
ãªããžã§ã¯ãæåããã°ã©ãã³ã°ã§ã¯ããã®åé¡ã¯ãã¡ãããããªã¢ãŒãã£ãºã ã«ãã£ãŠè§£æ±ºãããŸãã ã³ã¬ã¯ã·ã§ã³ã«ã¯ã¡ãœããããããããé©åãªã¡ãœãããåŒã³åºãããšã§ãå¿
èŠãªãã®ãåºåãšããŠååŸããŸãã éç£ã³ãŒãã®äœæã«äœ¿çšãããã©ã€ãã©ãªã¯ãããŸããŸãªã¿ã€ãã®ã³ã¬ã¯ã·ã§ã³ã®ã€ã³ã¿ãŒãã§ã€ã¹ãæäŸãããã©ã³ã¹ãã¥ãŒãµãŒã®äœ¿çšã䟿å©ã«ããŸãã
ãã©ã³ã¹ãã¥ãŒãµã®åºç€ãšãªããã³ãã¬ãŒããçè§£ãããã®èšèªã第äžçŽã®æ©èœãæäŸãã䟿å©ã§äŸ¿å©ãªæ©èœãè©äŸ¡ããã«ã¯ãäžèšã§ååã§ãããšèããŠããŸãã
倿åšïŒãŠãŒã¶ãŒãªã¹ãåŠç
ãã®è³æã§ã¯ã次ã®åé¡ã解決ããããã®ãªãã·ã§ã³ã瀺ããŸãããŠãŒã¶ãŒãšãŠãŒã¶ãŒã蚪ããå Žæã®ã»ããããããã©ã¡ããããã·ã¥ã³ãŒãã®ãªã¹ãã®åœ¢åŒã§è¡šç€ºãããŸãã åè¡ã®æåã®ã³ãŒãã¯ãŠãŒã¶ãŒã2çªç®ã®ã³ãŒãã¯èšªåããå Žæãããšãã°ã¬ã¹ãã©ã³ãåºã§ãã ãªã¹ãå
ã®ããŒã¿ã®é åºãéèŠã§ãã 課é¡ã¯ãå Žæéã®ã©ã®é·ç§»ãæã人æ°ãããããèŠã€ããããšã§ãã
ã€ãŸããæ¬¡ã®ãããªãªã¹ãããããŸãã
1a2ddc2, 5f2b932 f1a543f, 5890595 3abe124, bd11537 f1a543f, 5f2b932 f1a543f, bd11537 f1a543f, 5890595 1a2ddc2, bd11537 1a2ddc2, 5890595 3abe124, 5f2b932 f1a543f, 5f2b932 f1a543f, bd11537 f1a543f, 5890595 1a2ddc2, 5f2b932 1a2ddc2, bd11537 1a2ddc2, 5890595 ...
ãã®ãªã¹ããæ³šææ·±ãèŠããšããŠãŒã¶ãŒ
1a2ddc2
ãã³ãŒã
5890595
ã
5f2b932
ã
bd11537
ãããã³
5890595
ãŸãã åæã«ããŠãŒã¶ãŒ
f1a543f
ã¯ãå Žæ
5890595
ã
5f2b932
ã
bd11537
ãããã³
5890595
ã ãªã©ãªã©ã
人ã
ãéåžžã©ããžè¡ãã®ããç¥ãå¿
èŠããããšä»®å®ãããšããå ŽæAããããå ŽæBããžã®æã人æ°ã®ããé·ç§»ãèŠã€ããå¿
èŠããããŸãã
1a2ddc2
ã®ç§»åå±¥æŽã¯ã
5f2b932
ã
bd11537
ã
5890595
ã§ãã ããã¯ã圌ã«ãšã£ãŠããã®ãããªç§»è¡ã¹ããŒã ãå Žæããå Žæãžãšæ§ç¯ã§ããããšãæå³ããŸãã
5f2b932 -> bd11537 bd11537 -> 5890595 5890595 -> 5f2b932 5f2b932 -> bd11537 bd11537 -> 5890595
åãŠãŒã¶ãŒã«å¯ŸããŠåæ§ã®ãªã¹ããäœæããå¿
èŠãããããšã«æ³šæããŠãã ããã ãããå®äºããããæã人æ°ã®ãããã©ã³ãžã·ã§ã³ãèŠã€ããå¿
èŠããããŸãã åæ§ã®ã«ãŠã³ãã¯æ¬¡ã®ããã«ãªããŸãã
é·ç§»
5f2b932 -> bd11537
ããªã¹ãã«2å衚瀺ãããŸãã
é·ç§»
bd11537 -> 5890595
ã2åçºçããŸãã
é·ç§»
5890595 -> 5f2b932
ã¯äžåºŠã ãäŒã£ãã
ä»ããã¹ãããšã¯ããã¹ãŠã®ãŠãŒã¶ãŒã®ã¯ãªãã¯æ°ãèšç®ããæã人æ°ã®ãããã®ãèŠã€ããããšã§ãã ãã©ã³ã¹ãã¥ãŒãµãŒã䜿çšãããã®åé¡ã®è§£æ±ºçãæ¬¡ã«ç€ºããŸãã
const logContents = `1a2ddc2, 5f2b932 f1a543f, 5890595 3abe124, bd11537 f1a543f, 5f2b932 f1a543f, bd11537 f1a543f, 5890595 1a2ddc2, bd11537 1a2ddc2, 5890595 3abe124, 5f2b932 f1a543f, 5f2b932 f1a543f, bd11537 f1a543f, 5890595 1a2ddc2, 5f2b932 1a2ddc2, bd11537 1a2ddc2, 5890595`;
const asStream = function * (iterable) { yield * iterable; }; const lines = str => str.split('\n'); const streamOfLines = asStream(lines(logContents)); const datums = str => str.split(', '); const datumize = map(datums); const userKey = ([user, _]) => user; const pairMaker = () => { let wip = []; return reducer => (acc, val) => { wip.push(val); if (wip.length === 2) { const pair = wip; wip = wip.slice(1); return reducer(acc, pair); } else { return acc; } } } const sortedTransformation = (xfMaker, keyFn) => { const decoratedReducersByKey = new Map(); return reducer => (acc, val) => { const key = keyFn(val); let decoratedReducer; if (decoratedReducersByKey.has(key)) { decoratedReducer = decoratedReducersByKey.get(key); } else { decoratedReducer = xfMaker()(reducer); decoratedReducersByKey.set(key, decoratedReducer); } return decoratedReducer(acc, val); } } const userTransitions = sortedTransformation(pairMaker, userKey); const justLocations = map(([[u1, l1], [u2, l2]]) => [l1, l2]); const stringify = map(transition => transition.join(' -> ')); const transitionKeys = compose( stringify, justLocations, userTransitions, datumize ); const countsOf = (acc, val) => { if (acc.has(val)) { acc.set(val, 1 + acc.get(val)); } else { acc.set(val, 1); } return acc; } const greatestValue = inMap => Array.from(inMap.entries()).reduce( ([wasKeys, wasCount], [transitionKey, count]) => { if (count < wasCount) { return [wasKeys, wasCount]; } else if (count > wasCount) { return [new Set([transitionKey]), count]; } else { wasKeys.add(transitionKey); return [wasKeys, wasCount]; } } , [new Set(), 0] ); greatestValue( transduce(transitionKeys, countsOf, new Map(), streamOfLines) )
ãŸãšã
ãã®è³æãã誰ãããã©ã³ã¹ãã¥ãŒãµãŒãæ°žä¹
çãªããŒã«ã«ããã®ã«åœ¹ç«ã€ããšãé¡ã£ãŠããŸãã 圌ãã®ç ç©¶ãæãäžãããå Žåã¯ãããã«ãã©ã³ã¹ãã¥ãŒãµãŒã«é¢ããåªãã
è³æããããGitHubã®
transdusers-jsã©ã€ãã©ãªãŒããããŸãã
芪æãªãèªè
ïŒ JavaScriptãããžã§ã¯ãã§ãã©ã³ã¹ãã¥ãŒãµãŒã䜿çšããŠããŸããïŒ