Home > Mobile >  counting member from nested array of objects using ramda
counting member from nested array of objects using ramda

Time:12-22

[
    {
        'members': {
            'infants': [{ 'name': 'A' }],
            'adults': [{ 'name': 'B' }, { 'name': 'C' }],
            'children': [{ 'name': 'D' }],
        },
    },
    {
        'members': {
            'infants': [],
            'adults': [{ 'name': 'F' }, { 'name': 'G' }, { 'name': 'H' }],
            'children': [],
        },
    },
]

Here is how my data object looks like

and I tried to implement it like

const travelerCounter = compose(
  length,
  unnest,
  unnest,
  map(values),
  unnest,
  pluck('members')
)

I am not sure if it is a good solution or we can write it in compact way. It also shows the correct number but if I try to use it in TypeScript I am a TS error ts(2769)

CodePudding user response:

You can use R.chain with R.values and then flatten to a single array:

const { compose, length, flatten, chain, values, pluck } = R

const fn = compose(
  length, // get the length
  flatten, // flatten to a single array
  chain(values), // combine the values of all member objects
  pluck('members') // get members objects
)

const data = [{"members":{"infants":[{"name":"A"}],"adults":[{"name":"B"},{"name":"C"}],"children":[{"name":"D"}]}},{"members":{"infants":[],"adults":[{"name":"F"},{"name":"G"},{"name":"H"}],"children":[]}}]

const result = fn(data)

console.log(result)
<script src="https://cdnjs.cloudflare.com/ajax/libs/ramda/0.28.0/ramda.min.js" integrity="sha512-t0vPcE8ynwIFovsylwUuLPIbdhDj6fav2prN9fEu/VYBupsmrmk9x43Hvnt Mgn2h5YPSJOk7PMo9zIeGedD1A==" crossorigin="anonymous" referrerpolicy="no-referrer"></script>

TS types:

type Members = { members: Record<string, { name: string }[]> };

const fn: (v: Members[]) => number = compose(
  length, // get the length
  flatten, // flatten to a single array
  chain(values), // combine the values of all member objects
  pluck("members") // get members objects
);

Instead of flattening, you can also pluck the lengths, and then sum them:

const { compose, sum, pluck, length, chain, values } = R

const fn = compose(
  sum, // sum the lengths
  pluck('length'), // get the length of each members array
  chain(values), // combine values of all members objects
  pluck('members') // get members objects
)

const data = [{"members":{"infants":[{"name":"A"}],"adults":[{"name":"B"},{"name":"C"}],"children":[{"name":"D"}]}},{"members":{"infants":[],"adults":[{"name":"F"},{"name":"G"},{"name":"H"}],"children":[]}}]

const result = fn(data)

console.log(result)
<script src="https://cdnjs.cloudflare.com/ajax/libs/ramda/0.28.0/ramda.min.js" integrity="sha512-t0vPcE8ynwIFovsylwUuLPIbdhDj6fav2prN9fEu/VYBupsmrmk9x43Hvnt Mgn2h5YPSJOk7PMo9zIeGedD1A==" crossorigin="anonymous" referrerpolicy="no-referrer"></script>

TS types - in this case TS can't infer the types inside R.compose, so we'll need to provide a more verbose signature:

type Member = { name: string };
type MembersRecords = Record<string, Member[]>;
type Members = { members: MembersRecords };

const fn = compose<[Members[]], MembersRecords[], Member[][], number[], number>(
  sum, // sum the lengths
  pluck('length'), // get the length of each members array
  chain(values), // combine values of all members objects
  pluck('members') // get members objects
)
  • Related