我正在编写使用命令式样式将数字数组转换为新数据列表的代码,但我想使用像 ramdajs 这样的 javascript 库将其转换为函数式样式
代码背景 假设美元值(value) 共有 5 个硬币,25 美元,20 美元,... 1 美元。我们将不得不把钱换成美元硬币。用最少的金币
const data = [25, 20, 10, 5, 1];
const fn = n => data.map((v) => {
const numberOfCoin = Number.parseInt(n / v, 10);
const result = [v, numberOfCoin];
n %= v;
return numberOfCoin ? result : [];
}).filter(i => i.length > 0);
这段代码的结果应该是
fn(48) => [[25, 1], [20, 1], [1, 3]]
fn(100) => [[25, 4]]
最佳答案
我认为您已经有了一个很好的开始,但为了使其更具功能性,我需要进行一些更改:
- 使用表达式而不是语句(例如没有
return
) - 不改变数据(例如没有
n %= v
)
你不一定需要 Ramda:
const coins = value =>
[25, 20, 10, 5, 1].reduce(([acc, val], cur) =>
val < cur ? [acc, val] : [[...acc, [cur, Math.floor(val / cur)]], val % cur],
[[], value]
)[0];
console.log(coins(48));
console.log(coins(100));
如果您发现自己使用 map
然后使用 filter
,您很可能需要 reduce
。在我上面的函数 coins
中,迭代器返回一个数组,其中包含一对硬币数组和硬币数量以及每个步骤的减少值。
请注意,在每个步骤中,我都使用解构赋值来捕获对数组和单个参数中的减少值。
现在,当然也可以为此使用 Ramda:
const {compose, filter, last, mapAccum, flip} = R;
const mapIterator = (a, b) => [a % b, [b, Math.floor(a / b)]];
const withCoins = ([coins, number]) => number > 0;
const coins = compose(filter(withCoins), last, flip(mapAccum(mapIterator))([25, 20, 10, 5, 1]));
console.log(coins(48));
console.log(coins(100));
<script src="https://cdnjs.cloudflare.com/ajax/libs/ramda/0.26.1/ramda.min.js"></script>
编辑:正如 Scott 正确指出的那样,我上面的任何解决方案都会给您带来最少的改变。
事实证明,这比我预期的要复杂得多,我确定了一个我确信可以改进的解决方案:
我定义了 5 组硬币:
- [1]
- [5, 1]
- [10, 5, 1]
- [20, 10, 5, 1]
- [25, 20, 10, 5, 1]
我计算每组产生多少变化,只保留产生最少的那一个。
例如改变30
:
- 1×30
- 5×6
- 10 × 3
- 20 × 1, 10 × 1(保留这组)
- 25 × 1, 5 × 1
const {compose, pipe, sum, map, last, head, mapAccum, curry, flip, applyTo, sortBy, reject, not} = R;
const numCoins = compose(sum, map(last));
const changeFn = curry((coins, num) => mapAccum((cur, coin) => [cur % coin, [coin, Math.floor(cur / coin)]], num, coins)[1]);
const change1 = changeFn([1]);
const change2 = changeFn([5, 1]);
const change3 = changeFn([10, 5, 1]);
const change4 = changeFn([20, 10, 5, 1]);
const change5 = changeFn([25, 20, 10, 5, 1]);
const change = pipe(
applyTo,
flip(map)([
change1,
change2,
change3,
change4,
change5]),
sortBy(numCoins),
head,
reject(compose(not, last)));
console.log(change(30));
console.log(change(40));
console.log(change(48));
<script src="https://cdnjs.cloudflare.com/ajax/libs/ramda/0.26.1/ramda.min.js"></script>
关于javascript - 使用 ramda.js 将命令式风格转换为函数式风格,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54759788/