我有一个一个层次深度的数组,需要计算嵌套数组的长度和,即长度深度。
想出一个很好的惯用的方法和兰达一起做这件事。
我目前的解决办法还不够简洁。可能我漏掉了什么。
你能提出更好的建议吗?
const arr = [[1], [2, 3], [4, 5, 6]]
const lengthDeep = R.pipe(
R.map(R.prop('length')),
R.sum
)
console.log(lengthDeep(arr)) // 6<script src="//cdnjs.cloudflare.com/ajax/libs/ramda/0.24.1/ramda.min.js"></script>
PS:我正在学习Ramda,尝试将它应用到日常编码中。
发布于 2017-06-10 14:10:30
首先,您可以使用R.length而不是R.prop('length')。还可以考虑将数组扁平化,之后所需的结果是该数组的长度:
R.pipe(R.flatten, R.length)发布于 2017-06-11 02:23:20
虽然这是一个非常直截了当和简单的问题,但我认为这是一个有趣的问题。
到目前为止,有三个建议。我跳过了@ftor的回答,因为它忽略了您关于这是学习Ramda的一部分的评论。但我包括他关于折叠的评论。
以下是解决办法:
const lengthDeep = R.compose(R.sum, R.map(R.length));
const lengthDeep = R.compose(R.length, R.flatten);
const lengthDeep = R.reduce((total, xs) => total + R.length(xs), 0);(注意,我从pipe切换到了compose。当函数适合于一行时,我通常使用compose,但我并不认为pipe和compose是根本不同的解决方案。)
这些都符合对这一问题的不同理解。
Version A (R.compose(R.sum, R.map(R.length)))是最直接的,我认为它最接近于问题的最初表示:我们希望找到“嵌套数组的长度之和”。这个版本是最直接的:它找到这些长度,然后将它们相加在一起。(这是您的版本,通过@trincot的观察,R.length将代替R.prop('length')进行增强。)这是我会选择的。这是相当简单的,很明显它的作用。
Version B (R.compose(R.length, R.flatten))对应于这个问题的一个非常不同的概念。它回答了一个问题,“如果我把所有这些数组组合成一个,它会持续多长时间?”据我所知,它的唯一优点是它是最简单的代码。缺点是,运行可能需要更长的时间,而且肯定需要更多的空间。
Version C (R.reduce((total, xs) => total + R.length(xs), 0))包含了另一个概念。描述此解决方案的最佳方法是使用递归描述。空数组的深度长度为零。第一个元素具有n长度的数组的深度长度是n加上数组其余部分的深度长度。如果你是这么想问题的话,这个版本可能适合你。还有一次您可能会选择使用它:虽然我还没有进行测试,但我希望它具有更好的性能,因为它只在外部列表上循环一次。因此,如果您发现此函数是代码中的瓶颈(在引入任何性能优化之前要测试性能,对吗?),您可能会切换到它,尽管代码要复杂得多。(我不知道是否有一个合理的免费版本。我看不见一个简单的,这已经够可读的了。)
同样,我会选择版本A,除非有重要的事情促使我切换到版本C。不过,这似乎不太可能。
所有这一切可能是一个非常冗长的方式,不同意@ftor的评论:“当您实际使用map时,不应该使用fold数据结构。”相反,我想说的是,您应该使用最简单的代码来匹配问题的心理模型。这必须考虑到其他因素,如性能,但这应该是默认的。我对这个问题的理解完全符合“把所有的长度加在一起”的模式。
发布于 2017-06-11 10:01:49
这里还有一种方法,您可以使用一个名为mapReduce的小助手来实现它--我们可以使用Ramda的curry来实现它,这样它就可以像其他Rambda库成员一样共享一个神奇的咖喱接口。
mapReduce有效地采用了映射函数m和约简函数r,并创建了一个新的约简函数。这是一个有用的通用函数,因为它可以在任何您希望生成减速器的地方使用。
作为额外的奖励,此解决方案将只通过输入数组迭代一次(计算答案的最低要求)。
// mapReduce :: (a -> b) -> ((c, b) -> c) -> ((c, a) -> c)
const mapReduce = curry ((m, r) =>
(x, y) => r (x, m (y)))
// deepLength :: [[a]] -> Integer
const deepLength = xs =>
reduce (mapReduce (length, add), 0, xs)
// arr :: [[Integer]]
const arr = [[1], [2, 3], [4, 5, 6]]
console.log (deepLength (arr))
// 6为了演示mapReduce的多种用途,我将向您展示当事情稍微复杂一些时,它是如何处理的--同时仍然维护一个可读的程序
// mapReduce :: (a -> b) -> ((c, b) -> c) -> ((c, a) -> c)
const mapReduce = curry ((m, r) =>
(x, y) => r (x, m (y)))
// omap :: (a -> b) -> {k : a} -> {k : b}
const omap = curry ((f, o) =>
reduce (mapReduce (k => ({ [k]: f(o[k]) }), Object.assign), {}, keys(o)))
console.log (omap (add(10), {a: 1, b: 2, c: 3}))
// {"a": 11, "b": 12, "c": 13}https://stackoverflow.com/questions/44473974
复制相似问题