Rio
Rio

Reputation: 123

Simplifying calculation of arrays with Ramda

I would like to calculate the three arrays like this.

const Data =  {
   x : [2,4,6],
   y : [10,10,10],
   z : [5,5,5]
}

const XtimesYplusZ = zipWith (add, (zipWith (multiply, Data.x, Data.y)), Data.z)
console.log(XtimesYplusZ);//[25,45,65] 

This code works ok, but not very good in terms of readability. So, now I created calculation patterns that could be applied later on:

const calc1 =  ({x, y, z}) => x * y + z
console.log(calc1(Data)); //ERROR

This is not working. I have many different patterns such as ({x, y, z}) => x / y - z, ({x, y, z}) => (x + y) * z and so on. What is the standard calculation method for arrays something like this?

REPL

Upvotes: 1

Views: 69

Answers (1)

Ori Drori
Ori Drori

Reputation: 191986

In this example:

const calc1 =  ({x, y, z}) => x * y + z
console.log(calc1(Data)); //ERROR

You are trying to add and multiply arrays, and not the arrays' items.

Using R.zipWith won't work as well, since it requires actual arrays, and is limited to zipping 2 arrays at a time.

An easier solution would be to get the sub-arrays using R.props, transpose them ([[2, 10, 5], [4, 10, 5]]...), and then map and combine the values using your calc function (I've replace the object destructuring with array destructuring):

const { pipe, props, transpose, map } = R

const calc = ([x, y, z]) => x * y + z

const fn = pipe(props(['x', 'y', 'z']), transpose, map(calc))

const Data =  {
   x : [2,4,6],
   y : [10,10,10],
   z : [5,5,5]
}

const XtimesYplusZ = fn(Data)

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

This example show Scott's suggestion of extracting out the combination of R.transpose, and R.map to create a zipAllWith function:

const { curry, map, apply, transpose, pipe, props } = R

const zipAllWith = curry((fn, xss) => map(apply(fn), transpose(xss)));

const fn = pipe(props(['x', 'y', 'z']), zipAllWith((x, y, z) => x * y + z))

const Data =  {
   x : [2,4,6],
   y : [10,10,10],
   z : [5,5,5]
}

const XtimesYplusZ = fn(Data)

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

Upvotes: 2

Related Questions