-
Notifications
You must be signed in to change notification settings - Fork 89
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Deyan Totev
committed
Dec 20, 2023
1 parent
fe0b6b1
commit 558b2ac
Showing
4 changed files
with
194 additions
and
122 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,5 +1,17 @@ | ||
export function reduceBy(foo, bar){ | ||
if (arguments.length === 1) | ||
return _bar => reduceBy(foo, _bar) | ||
import { has } from "./has.js"; | ||
import { curry } from "./curry.js"; | ||
import { reduce } from "./reduce.js"; | ||
import { clone } from "./clone.js"; | ||
|
||
export function reduceByFn(valueFn, valueAcc, keyFn, list){ | ||
var xf = function(acc, elt) { | ||
var key = keyFn(elt); | ||
var value = valueFn(has(key, acc) ? acc[key] : clone(valueAcc), elt); | ||
|
||
acc[key] = value; | ||
return acc; | ||
} | ||
return reduce(xf, {}, list); | ||
} | ||
|
||
export const reduceBy = curry(reduceByFn) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,129 +1,179 @@ | ||
import { reduceBy as reduceByRamda } from 'ramda' | ||
|
||
import { reduceBy } from './reduceBy.js' | ||
import { prop } from './prop.js' | ||
|
||
test('happy', () => { | ||
const result = reduceBy() | ||
console.log(result) | ||
}) | ||
|
||
/* | ||
var R = require('../source/index.js') | ||
var eq = require('./shared/eq.js') | ||
var byType = R.prop('type') | ||
var sumValues = function (acc, obj) { | ||
const byType = prop('type') | ||
const sumValues = function (acc, obj){ | ||
return acc + obj.val | ||
} | ||
|
||
var sumInput = [ | ||
{type: 'A', val: 10}, | ||
{type: 'B', val: 20}, | ||
{type: 'A', val: 30}, | ||
{type: 'A', val: 40}, | ||
{type: 'C', val: 50}, | ||
{type: 'B', val: 60}, | ||
] | ||
describe('reduceBy', function () { | ||
var grade = function (score) { | ||
return score < 65 | ||
? 'F' | ||
: score < 70 | ||
? 'D' | ||
: score < 80 | ||
? 'C' | ||
: score < 90 | ||
? 'B' | ||
: 'A' | ||
} | ||
var students = [ | ||
{name: 'Abby', score: 84}, | ||
{name: 'Brad', score: 73}, | ||
{name: 'Chris', score: 89}, | ||
{name: 'Dianne', score: 99}, | ||
{name: 'Eddy', score: 58}, | ||
{name: 'Fred', score: 67}, | ||
{name: 'Gillian', score: 91}, | ||
{name: 'Hannah', score: 78}, | ||
{name: 'Irene', score: 85}, | ||
{name: 'Jack', score: 69}, | ||
] | ||
var byGrade = function (student) { | ||
return grade(student.score || 0) | ||
} | ||
const grade = function (score){ | ||
return score < 65 ? | ||
'F' : | ||
score < 70 ? | ||
'D' : | ||
score < 80 ? | ||
'C' : | ||
score < 90 ? | ||
'B' : | ||
'A' | ||
} | ||
|
||
it('splits the list into groups according to the grouping function', function () { | ||
var collectNames = function (acc, student) { | ||
return acc.concat(student.name) | ||
} | ||
eq(R.reduceBy(collectNames, [], byGrade, students), { | ||
A: ['Dianne', 'Gillian'], | ||
B: ['Abby', 'Chris', 'Irene'], | ||
C: ['Brad', 'Hannah'], | ||
D: ['Fred', 'Jack'], | ||
F: ['Eddy'], | ||
}) | ||
}) | ||
const byGrade = function (student){ | ||
return grade(student.score || 0) | ||
} | ||
|
||
it('splits the list into mutation-free groups', function () { | ||
var collectNames = function (acc, student) { | ||
acc.push(student.name) | ||
return acc | ||
} | ||
eq(R.reduceBy(collectNames, [], byGrade, students), { | ||
A: ['Dianne', 'Gillian'], | ||
B: ['Abby', 'Chris', 'Irene'], | ||
C: ['Brad', 'Hannah'], | ||
D: ['Fred', 'Jack'], | ||
F: ['Eddy'], | ||
}) | ||
test.only('splits the list into groups according to the grouping function', () => { | ||
const collectNames = function (acc, student){ | ||
return acc.concat(student.name) | ||
} | ||
expect(reduceBy( | ||
collectNames, [], byGrade, getStudents() | ||
)).toEqual({ | ||
A : [ 'Dianne', 'Gillian' ], | ||
B : [ 'Abby', 'Chris', 'Irene' ], | ||
C : [ 'Brad', 'Hannah' ], | ||
D : [ 'Fred', 'Jack' ], | ||
F : [ 'Eddy' ], | ||
}) | ||
}) | ||
|
||
it('returns an empty object if given an empty array', function () { | ||
eq(R.reduceBy(sumValues, 0, byType, []), {}) | ||
}) | ||
// test('splits the list into mutation-free groups', () => { | ||
// const collectNames = function (acc, student){ | ||
// acc.push(student.name) | ||
|
||
it('can act as a transducer', function () { | ||
var reduceToSumsBy = R.reduceBy(sumValues, 0) | ||
var sumByType = reduceToSumsBy(byType) | ||
eq( | ||
R.into( | ||
{}, | ||
R.compose(sumByType, R.map(R.adjust(1, R.multiply(10)))), | ||
sumInput | ||
), | ||
{A: 800, B: 800, C: 500} | ||
) | ||
eq( | ||
R.transduce( | ||
R.compose(sumByType, R.map(R.adjust(1, R.multiply(10)))), | ||
(result, input) => { | ||
result[input[0]] = result[input[0]] | ||
? result[input[0]] | ||
: 0 + input[1] | ||
return result | ||
}, | ||
{}, | ||
sumInput | ||
), | ||
{A: 800, B: 800, C: 500} | ||
) | ||
}) | ||
// return acc | ||
// } | ||
// expect(reduceBy( | ||
// collectNames, [], byGrade, getStudents( | ||
// )).toEqual({ | ||
// A : [ 'Dianne', 'Gillian' ], | ||
// B : [ 'Abby', 'Chris', 'Irene' ], | ||
// C : [ 'Brad', 'Hannah' ], | ||
// D : [ 'Fred', 'Jack' ], | ||
// F : [ 'Eddy' ], | ||
// }) | ||
// }) | ||
|
||
it('short circuits with reduced', function () { | ||
var collectNames = function (acc, student) { | ||
return student.name === 'Fred' | ||
? R.reduced(acc) | ||
: acc.concat(student.name) | ||
} | ||
eq(R.reduceBy(collectNames, [], byGrade, students), { | ||
A: ['Dianne'], | ||
B: ['Abby', 'Chris'], | ||
C: ['Brad'], | ||
F: ['Eddy'], | ||
}) | ||
}) | ||
test('returns an empty object if given an empty array', () => { | ||
expect(reduceBy( | ||
sumValues, 0, byType, [] | ||
)).toEqual({}) | ||
}) | ||
|
||
*/ | ||
// test('can act as a transducer', () => { | ||
// const reduceToSumsBy = reduceBy(sumValues, 0) | ||
// const sumByType = reduceToSumsBy(byType) | ||
// expect(R.into( | ||
// {}, | ||
// R.compose(sumByType, R.map(R.adjust(1, R.multiply(10)))), | ||
// sumInput | ||
// )).toEqual({ | ||
// A : 800, | ||
// B : 800, | ||
// C : 500, | ||
// }) | ||
// expect(R.transduce( | ||
// R.compose(sumByType, R.map(R.adjust(1, R.multiply(10)))), | ||
// (result, input) => { | ||
// result[ input[ 0 ] ] = result[ input[ 0 ] ] ? result[ input[ 0 ] ] : 0 + input[ 1 ] | ||
|
||
// return result | ||
// }, | ||
// {}, | ||
// sumInput | ||
// )).toEqual({ | ||
// A : 800, | ||
// B : 800, | ||
// C : 500, | ||
// }) | ||
// }) | ||
|
||
// test('short circuits with reduced', () => { | ||
// const collectNames = function (acc, student){ | ||
// return student.name === 'Fred' ? | ||
// R.reduced(acc) : | ||
// acc.concat(student.name) | ||
// } | ||
// expect(reduceBy( | ||
// collectNames, [], byGrade, getStudents( | ||
// )).toEqual({ | ||
// A : [ 'Dianne' ], | ||
// B : [ 'Abby', 'Chris' ], | ||
// C : [ 'Brad' ], | ||
// F : [ 'Eddy' ], | ||
// }) | ||
// }) | ||
|
||
function getStudents(){ | ||
return [ | ||
{ | ||
name : 'Abby', | ||
score : 84, | ||
}, | ||
{ | ||
name : 'Brad', | ||
score : 73, | ||
}, | ||
{ | ||
name : 'Chris', | ||
score : 89, | ||
}, | ||
{ | ||
name : 'Dianne', | ||
score : 99, | ||
}, | ||
{ | ||
name : 'Eddy', | ||
score : 58, | ||
}, | ||
{ | ||
name : 'Fred', | ||
score : 67, | ||
}, | ||
{ | ||
name : 'Gillian', | ||
score : 91, | ||
}, | ||
{ | ||
name : 'Hannah', | ||
score : 78, | ||
}, | ||
{ | ||
name : 'Irene', | ||
score : 85, | ||
}, | ||
{ | ||
name : 'Jack', | ||
score : 69, | ||
}, | ||
] | ||
} | ||
|
||
function getSumInput (){ | ||
return [ | ||
{ | ||
type : 'A', | ||
val : 10, | ||
}, | ||
{ | ||
type : 'B', | ||
val : 20, | ||
}, | ||
{ | ||
type : 'A', | ||
val : 30, | ||
}, | ||
{ | ||
type : 'A', | ||
val : 40, | ||
}, | ||
{ | ||
type : 'C', | ||
val : 50, | ||
}, | ||
{ | ||
type : 'B', | ||
val : 60, | ||
}, | ||
] | ||
} |