Examples for ramdajs

Table of Contents

Source code in https://github.com/mertnuhoglu/study/tree/master/js/ex/study_ramda/

mkdir -p ex/study_ramda && cd $_ && npm init -y && pnpm i parcel-bundler ramda

v01: Basics

const data = [
  {'id': 1, 'title': "a"},
  {'id': 2, 'title': "b"},
];
const getId = R.map(R.prop('id'));
console.log(getId(data));
node ex/study_ramda/ex01.js
## [ 1, 2 ]

v02: Basics

const data = [
  {'sub': {'id': 1, 'title': "a"}},
  {'sub': {'id': 2, 'title': "b"}},
];
const getId = R.map(R.compose(R.prop('id'), R.prop('sub')));
console.log(getId(data));
node ex/study_ramda/ex02.js
## [ 1, 2 ]

v03: Basics

I changed the input function of R.map to common object access notation:

const getId = R.map(R.compose(R.prop('id'), R.prop('sub')));
--->>>
const getId = R.map(e => e.sub.id);

This looks simpler than previous expression.

node ex/study_ramda/ex03.js
## [ 1, 2 ]

Tutorial by Andrew Burgess

Here, I follow the tutorial in Ramda By Example made by Andrew Burgess and the revised code written by Francisco Neto

The goal is to convert the following data structure into the next data structure:

const data = {
  'group1-perm1': true,
  'group1-perm2': false,
  'group2-perm1': false,
  'group2-perm2': true,
  'perm3': true,
  'perm4': false
};
// --->>>
const target = {
  'group1': [
    { value: 'group1-perm1', checked: true, 'label': 'perm1' }
  ],
// ...
};

v01: Convert key-value pairs into 2-tuples

First, we will convert the input data into an array of 2-tuples like that:

[ [ 'group1-perm1', true ], ... ]
R.map(([k, v]) => global[k] = v, R.toPairs(R));
const fn = compose(toPairs);
console.log(fn(data));
node ex/study_ramda/ab01.js
## [ [ 'group1-perm1', true ],
##   [ 'group1-perm2', false ],
##   [ 'group2-perm1', false ],
##   [ 'group2-perm2', true ],
##   [ 'perm3', true ],
##   [ 'perm4', false ] ]

v02: append an element

Now, we will convert 2-tuples into this structure:

[ { value: 'group1-perm1', checked: true, label: 'group1-perm1' }, ...

We can do this in two ways. First way:

const addLabel = ([value, checked]) => ({value, checked, label: value});
const fn = compose(map(addLabel), toPairs);
console.log(fn(data));
node ex/study_ramda/ab02.js
## [ { value: 'group1-perm1', checked: true, label: 'group1-perm1' },
##   { value: 'group1-perm2', checked: false, label: 'group1-perm2' },
##   { value: 'group2-perm1', checked: false, label: 'group2-perm1' },
##   { value: 'group2-perm2', checked: true, label: 'group2-perm2' },
##   { value: 'perm3', checked: true, label: 'perm3' },
##   { value: 'perm4', checked: false, label: 'perm4' } ]

The second way is to use chain function:

const addLabel = chain(append, head);
const fn = compose(map(addLabel), toPairs);
console.log(fn(data));

This code produces the following data structure which needs one more step:

[ [ 'group1-perm1', true, 'group1-perm1' ], ...
node ex/study_ramda/ab02b.js
## [ [ 'group1-perm1', true, 'group1-perm1' ],
##   [ 'group1-perm2', false, 'group1-perm2' ],
##   [ 'group2-perm1', false, 'group2-perm1' ],
##   [ 'group2-perm2', true, 'group2-perm2' ],
##   [ 'perm3', true, 'perm3' ],
##   [ 'perm4', false, 'perm4' ] ]

The first version is easier to understand. Let’s keep that one.

v03: Text substitution using regex

Now we want to update label’s value as such:

[ { value: 'group1-perm1', checked: true, label: 'group1-perm1' }, ...
--->>>
[ { value: 'group1-perm1', checked: true, label: 'perm1' }, ...
const getLabel = R.compose(R.head, R.match(/perm[0-9]/g));
const addLabel = ([value, checked]) => ({value, checked, label: getLabel(value)});
node ex/study_ramda/ab03.js
## [ { value: 'group1-perm1', checked: true, label: 'perm1' },
##   { value: 'group1-perm2', checked: false, label: 'perm2' },
##   { value: 'group2-perm1', checked: false, label: 'perm1' },
##   { value: 'group2-perm2', checked: true, label: 'perm2' },
##   { value: 'perm3', checked: true, label: 'perm3' },
##   { value: 'perm4', checked: false, label: 'perm4' } ]

v04: Group items using groupBy

[ { value: 'group1-perm1', checked: true, label: 'perm1' }, ...
--->>>
{ 'group1-perm1': [ { value: 'group1-perm1', checked: true, label: 'perm1' } ], ...
const groupName = R.prop('value');
const fn = compose(R.groupBy(groupName), map(addLabel), toPairs);
node ex/study_ramda/ab04.js
## { 'group1-perm1': [ { value: 'group1-perm1', checked: true, label: 'perm1' } ],
##   'group1-perm2':
##    [ { value: 'group1-perm2', checked: false, label: 'perm2' } ],
##   'group2-perm1':
##    [ { value: 'group2-perm1', checked: false, label: 'perm1' } ],
##   'group2-perm2': [ { value: 'group2-perm2', checked: true, label: 'perm2' } ],
##   perm3: [ { value: 'perm3', checked: true, label: 'perm3' } ],
##   perm4: [ { value: 'perm4', checked: false, label: 'perm4' } ] }

v05: Group items 02

{ 'group1-perm1': [ { value: 'group1-perm1', checked: true, label: 'perm1' } ], ...
--->>>
{ group1:
   [ { value: 'group1-perm1', checked: true, label: 'perm1' },
     { value: 'group1-perm2', checked: false, label: 'perm2' } ],
const getGroup = R.compose(R.defaultTo('general'), R.head, R.match(/group[0-9]/g));
const groupName = R.compose(getGroup, R.prop('value'));
const fn = compose(R.groupBy(groupName), map(addLabel), toPairs);
node ex/study_ramda/ab05.js
## { group1:
##    [ { value: 'group1-perm1', checked: true, label: 'perm1' },
##      { value: 'group1-perm2', checked: false, label: 'perm2' } ],
##   group2:
##    [ { value: 'group2-perm1', checked: false, label: 'perm1' },
##      { value: 'group2-perm2', checked: true, label: 'perm2' } ],
##   general:
##    [ { value: 'perm3', checked: true, label: 'perm3' },
##      { value: 'perm4', checked: false, label: 'perm4' } ] }

v06: pipe instead of compose

R.pipe and R.compose are similar but they execute the functions in reverse order. R.pipe executes the input functions from left-to-right. compose executes from right-to-left. Thus pipe is easier to read.

const fn = compose(R.groupBy(groupName), map(addLabel), toPairs);
--->>>>
const fn = pipe(
  toPairs,
  map(addLabel), 
  R.groupBy(groupName), 
);
node ex/study_ramda/ab06.js
## { group1:
##    [ { value: 'group1-perm1', checked: true, label: 'perm1' },
##      { value: 'group1-perm2', checked: false, label: 'perm2' } ],
##   group2:
##    [ { value: 'group2-perm1', checked: false, label: 'perm1' },
##      { value: 'group2-perm2', checked: true, label: 'perm2' } ],
##   general:
##    [ { value: 'perm3', checked: true, label: 'perm3' },
##      { value: 'perm4', checked: false, label: 'perm4' } ] }