有没有其他方法可以使用 Ramda 从数组中获取中间元素?
Is there alternative to get middle element from array using Ramda?
我试过这段代码,它产生了我想要的结果:
const {
__,
compose,
converge,
divide,
identity,
length,
prop
} = require("ramda");
const div2 = divide(__, 2);
const lengthDiv2 = compose(Math.floor, div2, length);
const midElement = converge(prop, [lengthDiv2, identity]);
console.log(midElement([1, 5, 4]); //5
但我不知道是否有另一种方法可以从数组中获取 属性,特别是 midElement 函数的其他一些实现?
您可以通过链接 R.nth and lengthDiv2
because according to R.chain 文档(和@ScottSauyet)来创建 midElement
:
If second argument is a function, chain(f, g)(x) is equivalent to
f(g(x), x).
在这种情况下 g
是 lengthDiv2
,f
是 R.nth,x
是数组。因此,结果将是 R.nth(lengthDiv2(array), array)
,这将是 return 中间项。
const { compose, flip, divide, length, chain, nth } = R;
const div2 = flip(divide)(2); // create the function using flip
const lengthDiv2 = compose(Math.floor, div2, length);
const midElement = chain(nth, lengthDiv2); // chain R.nth and lengthDiv2
console.log(midElement([1, 5, 4])); //5
<script src="https://cdnjs.cloudflare.com/ajax/libs/ramda/0.27.0/ramda.js"></script>
简化
是的,midElement
有一种更简单的写法。这感觉有点干净:
const div2 = divide (__, 2)
const lengthDiv2 = compose (floor, div2, length)
const midElement = chain (nth, lengthDiv2)
console.log (midElement ([8, 6, 7, 5, 3, 0, 9])) //=> 5
console.log (midElement ([8, 6, 7, 5, 3, 0])) //=> 5
<script src="//cdnjs.cloudflare.com/ajax/libs/ramda/0.27.0/ramda.js"></script><script>
const {divide, __, compose, length, chain, nth} = R
const {floor} = Math </script>
(我们在这里选择 nth
over prop
只是因为它在语义上更正确。nth
特定于数组及其索引。prop
之所以起作用只是因为 Javascript 在普通对象之上构建它的数组。)
chain
is an interesting function. You can find many more details in its FantasyLand specification。但对于我们的案例,重要的一点是它如何与函数一起工作。
chain (f, g) //=> (x) => f (g (x)) (x)
这说明了(至少在这里)它是 converge
的更简单替代方法。
请注意,此版本与您的原始版本一样,在列表长度为偶数时选择两个中心值中的第二个。我通常发现我们更自然地选择第一个。也就是说,例如,midpoint([3, 6, 9, 12])
通常是 6
。要改变这一点,我们可以在除法之前简单地添加一个递减操作:
const midpoint = chain(nth, compose(floor, divide(__, 2), dec, length))
但是为什么呢?
然而,Ramda 在这里并没有提供太多有用的东西。 Ramda(免责声明:我是其主要作者之一)为许多问题提供帮助。但它是一个工具,我不建议使用它,除非它能让你的代码更干净。
这个版本在我看来更容易理解:
const midpoint = (xs) => xs[Math.floor ((xs.length / 2))]
console.log (midpoint ([8, 6, 7, 5, 3, 0, 9])) //=> 5
console.log (midpoint ([8, 6, 7, 5, 3, 0])) //=> 5
如果你想要上面的递减行为,或者这个版本:
const midpoint = (xs) => xs[Math.floor (((xs.length - 1) / 2))]
console.log (midpoint ([8, 6, 7, 5, 3, 0, 9])) //=> 5
console.log (midpoint ([8, 6, 7, 5, 3, 0])) //=> 7
另一种选择
但是写这样一个函数有很多不同的方法。虽然我不会真的推荐它,因为它的性能无法比较,递归解决方案非常优雅:
// choosing the first central option
const midpoint = (xs) => xs.length <= 2 ? xs[0] : midpoint (xs.slice(1, -1))
// choosing the second central option
const midpoint = (xs) => xs.length <= 2 ? xs[xs.length - 1] : midpoint (xs.slice(1, -1))
如果剩下的不超过两个,则这些只取两个中心元素中的一个,否则递归取删除第一个和最后一个元素后剩余的数组的中点。
要记住什么
我是 Ramda 的创始人,我为这个库感到自豪。但我们需要记住,它只是一个图书馆。它应该使某种编码风格更容易,但它不应该规定任何特定的风格。当它使您的代码更简单、更易于维护、更一致或更高效时,请使用它。永远不要仅仅因为可以就使用它。
我试过这段代码,它产生了我想要的结果:
const {
__,
compose,
converge,
divide,
identity,
length,
prop
} = require("ramda");
const div2 = divide(__, 2);
const lengthDiv2 = compose(Math.floor, div2, length);
const midElement = converge(prop, [lengthDiv2, identity]);
console.log(midElement([1, 5, 4]); //5
但我不知道是否有另一种方法可以从数组中获取 属性,特别是 midElement 函数的其他一些实现?
您可以通过链接 R.nth and lengthDiv2
because according to R.chain 文档(和@ScottSauyet)来创建 midElement
:
If second argument is a function, chain(f, g)(x) is equivalent to f(g(x), x).
在这种情况下 g
是 lengthDiv2
,f
是 R.nth,x
是数组。因此,结果将是 R.nth(lengthDiv2(array), array)
,这将是 return 中间项。
const { compose, flip, divide, length, chain, nth } = R;
const div2 = flip(divide)(2); // create the function using flip
const lengthDiv2 = compose(Math.floor, div2, length);
const midElement = chain(nth, lengthDiv2); // chain R.nth and lengthDiv2
console.log(midElement([1, 5, 4])); //5
<script src="https://cdnjs.cloudflare.com/ajax/libs/ramda/0.27.0/ramda.js"></script>
简化
是的,midElement
有一种更简单的写法。这感觉有点干净:
const div2 = divide (__, 2)
const lengthDiv2 = compose (floor, div2, length)
const midElement = chain (nth, lengthDiv2)
console.log (midElement ([8, 6, 7, 5, 3, 0, 9])) //=> 5
console.log (midElement ([8, 6, 7, 5, 3, 0])) //=> 5
<script src="//cdnjs.cloudflare.com/ajax/libs/ramda/0.27.0/ramda.js"></script><script>
const {divide, __, compose, length, chain, nth} = R
const {floor} = Math </script>
(我们在这里选择 nth
over prop
只是因为它在语义上更正确。nth
特定于数组及其索引。prop
之所以起作用只是因为 Javascript 在普通对象之上构建它的数组。)
chain
is an interesting function. You can find many more details in its FantasyLand specification。但对于我们的案例,重要的一点是它如何与函数一起工作。
chain (f, g) //=> (x) => f (g (x)) (x)
这说明了(至少在这里)它是 converge
的更简单替代方法。
请注意,此版本与您的原始版本一样,在列表长度为偶数时选择两个中心值中的第二个。我通常发现我们更自然地选择第一个。也就是说,例如,midpoint([3, 6, 9, 12])
通常是 6
。要改变这一点,我们可以在除法之前简单地添加一个递减操作:
const midpoint = chain(nth, compose(floor, divide(__, 2), dec, length))
但是为什么呢?
然而,Ramda 在这里并没有提供太多有用的东西。 Ramda(免责声明:我是其主要作者之一)为许多问题提供帮助。但它是一个工具,我不建议使用它,除非它能让你的代码更干净。
这个版本在我看来更容易理解:
const midpoint = (xs) => xs[Math.floor ((xs.length / 2))]
console.log (midpoint ([8, 6, 7, 5, 3, 0, 9])) //=> 5
console.log (midpoint ([8, 6, 7, 5, 3, 0])) //=> 5
如果你想要上面的递减行为,或者这个版本:
const midpoint = (xs) => xs[Math.floor (((xs.length - 1) / 2))]
console.log (midpoint ([8, 6, 7, 5, 3, 0, 9])) //=> 5
console.log (midpoint ([8, 6, 7, 5, 3, 0])) //=> 7
另一种选择
但是写这样一个函数有很多不同的方法。虽然我不会真的推荐它,因为它的性能无法比较,递归解决方案非常优雅:
// choosing the first central option
const midpoint = (xs) => xs.length <= 2 ? xs[0] : midpoint (xs.slice(1, -1))
// choosing the second central option
const midpoint = (xs) => xs.length <= 2 ? xs[xs.length - 1] : midpoint (xs.slice(1, -1))
如果剩下的不超过两个,则这些只取两个中心元素中的一个,否则递归取删除第一个和最后一个元素后剩余的数组的中点。
要记住什么
我是 Ramda 的创始人,我为这个库感到自豪。但我们需要记住,它只是一个图书馆。它应该使某种编码风格更容易,但它不应该规定任何特定的风格。当它使您的代码更简单、更易于维护、更一致或更高效时,请使用它。永远不要仅仅因为可以就使用它。