Home > Software design >  Reduce multiple properties in array of array of objects and omit other properties using Ramda
Reduce multiple properties in array of array of objects and omit other properties using Ramda

Time:03-30

I have this array of arrays with objects:

const data = [
  [
    {
      index: 320,
      blocks: 2,
      value: '31011784785',
      participants: 1222,
      cost: '1286828506'
    },
    {
      index: 319,
      blocks: 0,
      value: '111306385',
      participants: 18,
      cost: '0'
    },
    {
      index: 318,
      blocks: 0,
      value: '14550473',
      participants: 10,
      cost: '0'
    }
  ],
  [
    {
      index: 320,
      blocks: 1,
      value: '7089001673',
      participants: 492,
      cost: '648196615'
    },
    {
      index: 319,
      blocks: 0,
      value: '13551137',
      participants: 8,
      cost: '0'
    },
    {
      index: 318,
      blocks: 0,
      value: '11499815',
      participants: 5,
      cost: '0'
    }
  ],
  [
    {
      index: 320,
      blocks: 1,
      value: '408900161',
      participants: 200,
      cost: '648196615'
    },
    {
      index: 319,
      blocks: 0,
      value: '23551231',
      participants: 10,
      cost: '0'
    },
    {
      index: 318,
      blocks: 0,
      value: '104324219',
      participants: 5,
      cost: '0'
    }
  ]
]

I would like to make a single array with objects that will have just the properties index, value, and participants where value and participants will be the sum of the 3 arrays. Eg:

[
  {
      index: 320,
      value: 38509686619,
      participants: 1914,
  },
  {
      index: 319,
      value: 148408753,
      participants: 36,
  },
  {
     ...
  }
]

I would also like the value field to be a BigInt.

Inspired by this answer I made something that works but it's way too long and cumbersome.

This question is different from Reduce Array of Array of Objects Using Ramda because I need two object property values and I don't know how to do this.

CodePudding user response:

After flattening, the array of arrays, you should map and pick the wanted properties and convert values to a number, and then group by, and combine each group to a single object.

const { mergeWithKey, pipe, flatten, map, pick, evolve, groupBy, prop, reduce, values } = R

// merge deep and combine properties value
const combine = mergeWithKey((k, l, r) => k === 'value' || k === 'participants' ? l   r : r)

const mergeData = pipe(
  flatten, // flatten to a single array
  map(pipe(
    pick(['index', 'value', 'participants']), // pick wanted properties
    evolve({ value: Number }) // convert values to a number
  )),
  groupBy(prop('index')), // group by the name
  map(reduce(combine, {})), // combine each group to a single object
  values, // convert back to array
)

const data = [[{"index":320,"blocks":2,"value":"31011784785","participants":1222,"cost":"1286828506"},{"index":319,"blocks":0,"value":"111306385","participants":18,"cost":"0"},{"index":318,"blocks":0,"value":"14550473","participants":10,"cost":"0"}],[{"index":320,"blocks":1,"value":"7089001673","participants":492,"cost":"648196615"},{"index":319,"blocks":0,"value":"13551137","participants":8,"cost":"0"},{"index":318,"blocks":0,"value":"11499815","participants":5,"cost":"0"}],[{"index":320,"blocks":1,"value":"408900161","participants":200,"cost":"648196615"},{"index":319,"blocks":0,"value":"23551231","participants":10,"cost":"0"},{"index":318,"blocks":0,"value":"104324219","participants":5,"cost":"0"}]]

const results = mergeData(data)

console.log(results)
<script src="https://cdnjs.cloudflare.com/ajax/libs/ramda/0.27.1/ramda.min.js" integrity="sha512-rZHvUXcc1zWKsxm7rJ8lVQuIr1oOmm7cShlvpV0gWf0RvbcJN6x96al/Rp2L2BI4a4ZkT2/YfVe/8YvB2UHzQw==" crossorigin="anonymous"></script>

CodePudding user response:

Vanila JS solution:

const data = [[{"index":320,"blocks":2,"value":"31011784785","participants":1222,"cost":"1286828506"},{"index":319,"blocks":0,"value":"111306385","participants":18,"cost":"0"},{"index":318,"blocks":0,"value":"14550473","participants":10,"cost":"0"}],[{"index":320,"blocks":1,"value":"7089001673","participants":492,"cost":"648196615"},{"index":319,"blocks":0,"value":"13551137","participants":8,"cost":"0"},{"index":318,"blocks":0,"value":"11499815","participants":5,"cost":"0"}],[{"index":320,"blocks":1,"value":"408900161","participants":200,"cost":"648196615"},{"index":319,"blocks":0,"value":"23551231","participants":10,"cost":"0"},{"index":318,"blocks":0,"value":"104324219","participants":5,"cost":"0"}]];


const result = Object.values(data.flat()
  .reduce((acc, { index, value, participants }) => {
    acc[index] ??= { index, value: 0, participants: 0 };
    acc[index].value  = Number(value);
    acc[index].participants  = Number(participants);
  
    return acc;
}, {}));

console.log(result);
.as-console-wrapper{min-height: 100%!important; top: 0}

  • Related