拉姆达。从数组创建固定长度的子数组

Ramda. create subarray with fixed length from array

我有一个包含数据的数组,我想将其转换为只有 5 个元素长的数组。 例如:

[1,2,3,4,5,6] => [1,2,3,4,5]

或者,如果原始数组中的元素少于 5 个

[1,2,3] => [1,2,3, undefined, undefined]

(我需要 'undefined' 值,因为我想稍后迭代它们并填充一些默认值)。 所以问题是如何用 Ramda 的方式来做?

谢谢!!

考虑 "the Ramda way." Ramda(免责声明:我是 Ramda 的作者之一)只是一个库,一个工具包时,您可能需要保持警惕。它并不是要规定任何关于如何编写代码的内容,只是为了让以某种方式编写代码更容易...当该方式合适时

也就是说,用 Ramda 写这个很容易:

const {compose, take, concat, __, repeat} = R

const toFixed = (n, d) => compose(take(n), concat(__, repeat(d, n)))
const take5 = toFixed(5, undefined)

console.log(take5([1, 2, 3, 4, 5, 6])) //=> [1, 2, 3, 4, 5]
console.log(take5([1, 2, 3]))          //=> [1, 2, 3, undefined, undefined]
<script src="//cdnjs.cloudflare.com/ajax/libs/ramda/0.25.0/ramda.js"></script>

请注意,这为您提供了在填充时选择默认值的可能性(如果有帮助的话)。这可能对您有用,也可能没有用,但您可以根据需要选择 undefined

这并非完全没有意义。能不能弄成这样?想必。但它是可读的(大部分*),我可能不会再费心去读了。

不过,最大的问题是 Ramda 与我们在没有库的情况下编写的内容相比并没有提供太多改进。这是另一个没有 Ramda 的版本:

const toFixed2 = (n, d) => (xs) => xs.concat(Array(n).fill(d)).slice(0, n)
const brubeck = toFixed2(5, undefined)

console.log(brubeck([1, 2, 3, 4, 5, 6])) //=> [1, 2, 3, 4, 5]
console.log(brubeck([1, 2, 3]))          //=> [1, 2, 3, undefined, undefined]

如果发现 Ramda 版本的可读性稍微好一点,而且更短一些。但这并不是一个巨大的改进。我永远不会仅仅为了这个小改进而将 Ramda 引入代码库。但如果我已经在使用 Ramda,我会选择那个版本。

更新

这个答案的评论中的讨论提到了另一种解决方案,与问题评论中的一个相关:

const desmond = (arr) => (arr = arr.slice(0), arr.length = 5, arr)

(如果您不介意改变原始数组,也可以跳过 slice 步骤。)

这当然与上面的 API 不同,并且不允许您提供默认值。但还有一个细微差别。

所有解决方案都得到报告长度为 5 的数组;它们具有相同的 JSON.strigify 输出,它们为每个索引报告相同的值,但是:

3 in take5([1, 2, 3])   //=> true
3 in brubeck([1, 2, 3]) //=> true
3 in desmond([1, 2, 3]) //=> false

因此存在可发现的差异。最后一个解决方案会更改数组的长度,但不会在缺失的索引处放置任何内容。前两个这样做。鉴于我们放置的是值 undefined,这可能根本无关紧要,但有时这种微妙之处可能会咬我们。


(*) 占位符 (__) 似乎总是导致函数对某些人而言可读性较差,而对其他人而言更是如此。如果愿意,可以将 concat(__, foo) 替换为 flip(concat)(foo)