Reputation: 941
I'm trying to write a function which converts cm
to feet
and inches
cmToFtIn(30) === {"feet": 1, "inches": 0}
cmToFtIn(29) === {"feet": 0, "inches": 11}
What I've done already is this complicated function
const cmToFeetMultiplier = multiply(1/30.5)
const ftToInMultiplier = multiply(12)
const floor = (num) => Math.floor(num)
const round = (num) => Math.round(num)
const cmToFtIn = pipe(
cmToFeetMultiplier,
juxt([identity, floor]),
juxt([identity, pipe(apply(subtract), ftToInMultiplier, round)]),
flatten,
cond([
[pipe(nth(2), equals(12)), (d) => ({feet: d[1] + 1, inches: 0})],
[always(true), (d) => ({feet: d[1], inches: d[2]})],
])
)
Maybe someone has some advice as to how to simplify it?
Upvotes: 3
Views: 2389
Reputation: 50787
Unless this is an exercise to learn Ramda, I would suggest that Ramda is not the right tool for this job. I'm one of the authors of Ramda, and a big fan, but it's a tool designed to help make an FP style more palatable in JS, not a general-purpose utility library.
The issue is that this function can be written quite simply in vanilla JS:
const cmToInFt = (cm, inches = Math .round (cm / 2.54)) => ({
feet: Math .floor (inches / 12),
inches: inches % 12
})
const myHeight = cmToInFt (185)
console .log (myHeight)
Or, if you don't like default parameters, it might be:
const cmToInFt = (cm) => {
const inches = Math .round (cm / 2.54)
return {
feet: Math .floor (inches / 12),
inches: inches % 12
}
}
Ramda can add little to that. Obviously, as your approach and customcommander's answer show, you can use Ramda functions to help, and a little dose of compose
is often useful. But this (which is very similar to the answer from Aadit M Shah, structured slightly differently) is already clean and readable. I see little that will make it easier to work with.
Upvotes: 2
Reputation: 18901
When you google "cm to inch":
and "cm to foot":
We can then build a inch
and foot
functions:
const inch = flip(divide)(2.54);
const foot = flip(divide)(30.48);
inch(30); //=> 11.811023622047244
foot(30); //=> 0.984251968503937
If you need to return an object {inch, foot}
from a value in cm you can without Ramda:
const cmToFtIn = cm => ({inch: inch(cm), foot: foot(cm)});
cmToFtIn(30);
//=> {"foot": 0.984251968503937, "inch": 11.811023622047244}
With Ramda:
const cmToFtIn = applySpec({inch, foot});
cmToFtIn(30);
//=> {"foot": 0.984251968503937, "inch": 11.811023622047244}
Personally I'd recommend that you do not return rounded values directly from inch
and foot
functions. You can apply a second pass to round them where you need to do so. Two options:
Apply Math.round
on your {inch, foot}
object:
map(Math.round, cmToFtIn(30));
//=> {"foot": 1, "inch": 12}
Or compose Math.round
and inch
/foot
functions:
const cmToFtIn = applySpec({
inch: compose(Math.round, inch),
foot: compose(Math.round, foot)
});
cmToFtIn(30);
//=> {"foot": 1, "inch": 12}
Upvotes: 2
Reputation: 74204
There are 2.54
centimeters in an inch. Hence, we have the equation.
const cmToInches = cm => cm / 2.54;
There are 12
inches in a foot. Hence, we have the equation.
const inchesToFtIn = inches => ({
feet: Math.floor(inches / 12),
inches: inches % 12,
});
Now, to convert centimeters to feet and inches we just compose these two functions.
const cmToInches = cm => cm / 2.54;
const inchesToFtIn = inches => ({
feet: Math.floor(inches / 12),
inches: inches % 12,
});
const cmToFtIn = cm => inchesToFtIn(cmToInches(cm));
console.log(cmToFtIn(30.48)); // 1 foot
console.log(cmToFtIn(27.94)); // 11 inches
If you need to round the inches then that's a small change.
const cmToInches = cm => cm / 2.54;
const inchesToFtIn = inches => ({
feet: Math.floor(inches / 12),
inches: inches % 12,
});
const cmToFtIn = cm => inchesToFtIn(Math.round(cmToInches(cm)));
console.log(cmToFtIn(30)); // 1 foot
console.log(cmToFtIn(29)); // 11 inches
Hope that helps.
Upvotes: 1