使用 Ramda `range` 进行复制,但需要每 3 次插入一次(React)
Using Ramda `range` to duplicate, but need to interject at every 3rd (React)
我目前正在使用 Ramda 为记录的每个 perk
实例输出 Material-UI CheckCircle
。它们最多可以有 18 个,所以我也用它来继续计数 past the perk
到最大值 18
以显示潜在的最大值。
{R.range(0, this.props.perkProgress).map(() => <CheckCircle key={uid()} /> )}
{R.range(this.props.perkProgress, 18).map(() => <CheckBoxOutline key={uid()} /> )}
这两行完美地工作,但是我还需要在每个 'third' 行之后插入一些东西 - 而是一个框,或者一个复选标记。因为我不相信我可以用 Ramda 做,我怎么能用普通的 JS 感觉来写这个(或者把它包装在一个函数中;两者之一)来获得我需要的输出?
this.props.perkProgress
始终是 0 到 18 之间的整数。
如果他们有“5”,我希望有 5 个复选标记和 13 个空方块。
添加一个 terrible drawing 当前功能部分,以及所需的最终结果:
这可以使用 Ramda 实现,方法是首先使用 R.splitEvery
then adding the separator between each split list using R.intersperse
and finally joining the split lists back together with R.unnest
分割元素列表。
(n.b。为了简洁起见,我用下面的字符串替换了你的 JSX)
// inserts `sep` between every `n` elements of a list `xs`
const separateEvery = (sep, n, xs) =>
R.unnest(R.intersperse([sep], R.splitEvery(n, xs)))
const genElements = (totalSize, progress) =>
separateEvery('Separator', 3, R.concat(
R.repeat('CheckCircle', progress),
R.repeat('CheckBoxOutline', totalSize - progress)
))
console.log(genElements(18, 7))
<script src="//cdnjs.cloudflare.com/ajax/libs/ramda/0.25.0/ramda.min.js"></script>
更新以回应以下评论
向每个生成的元素添加键的一种方法是使用 React.cloneElement
.
映射每个元素
const genElementsWithKey = R.pipe(
genElements,
R.addIndex(R.map)((el, key) => React.cloneElement(el, {key}))
)
或者,如果您出于某种原因不想使用 cloneElement
,那么您可以使用 R.zipWith
换出 R.intersperse
,以创建一个唯一的分隔符元素以在每个组之间插入元素数。
const createCircle = _ => '<CheckCircle key={uid()} />'
const createCheckBox = _ => '<CheckBoxOutline key={uid()} />'
const createSeparator = _ => '<Separator key={uid()} />'
const genElements = (totalSize, progress) => {
const splitEls = R.splitEvery(3, R.concat(
R.map(createCircle, R.range(0, progress)),
R.map(createCheckBox, R.range(progress, totalSize))
))
const firstSplitGroup = splitEls[0]
const remainingSplitGroups = R.tail(splitEls)
// create a list of separators matching the number of elements in remainingSplitGroups
const separators = R.map(createSeparator, R.range(0, remainingSplitGroups.length))
return R.concat(
// keep the first split group as is
firstSplitGroup,
// prepend a separator to each of the remaining split groups
R.unnest(R.zipWith(R.prepend, separators, remainingSplitGroups))
)
}
console.log(genElements(18, 7))
<script src="//cdnjs.cloudflare.com/ajax/libs/ramda/0.25.0/ramda.min.js"></script>
我目前正在使用 Ramda 为记录的每个 perk
实例输出 Material-UI CheckCircle
。它们最多可以有 18 个,所以我也用它来继续计数 past the perk
到最大值 18
以显示潜在的最大值。
{R.range(0, this.props.perkProgress).map(() => <CheckCircle key={uid()} /> )}
{R.range(this.props.perkProgress, 18).map(() => <CheckBoxOutline key={uid()} /> )}
这两行完美地工作,但是我还需要在每个 'third' 行之后插入一些东西 - 而是一个框,或者一个复选标记。因为我不相信我可以用 Ramda 做,我怎么能用普通的 JS 感觉来写这个(或者把它包装在一个函数中;两者之一)来获得我需要的输出?
this.props.perkProgress
始终是 0 到 18 之间的整数。
如果他们有“5”,我希望有 5 个复选标记和 13 个空方块。
添加一个 terrible drawing 当前功能部分,以及所需的最终结果:
这可以使用 Ramda 实现,方法是首先使用 R.splitEvery
then adding the separator between each split list using R.intersperse
and finally joining the split lists back together with R.unnest
分割元素列表。
(n.b。为了简洁起见,我用下面的字符串替换了你的 JSX)
// inserts `sep` between every `n` elements of a list `xs`
const separateEvery = (sep, n, xs) =>
R.unnest(R.intersperse([sep], R.splitEvery(n, xs)))
const genElements = (totalSize, progress) =>
separateEvery('Separator', 3, R.concat(
R.repeat('CheckCircle', progress),
R.repeat('CheckBoxOutline', totalSize - progress)
))
console.log(genElements(18, 7))
<script src="//cdnjs.cloudflare.com/ajax/libs/ramda/0.25.0/ramda.min.js"></script>
更新以回应以下评论
向每个生成的元素添加键的一种方法是使用 React.cloneElement
.
const genElementsWithKey = R.pipe(
genElements,
R.addIndex(R.map)((el, key) => React.cloneElement(el, {key}))
)
或者,如果您出于某种原因不想使用 cloneElement
,那么您可以使用 R.zipWith
换出 R.intersperse
,以创建一个唯一的分隔符元素以在每个组之间插入元素数。
const createCircle = _ => '<CheckCircle key={uid()} />'
const createCheckBox = _ => '<CheckBoxOutline key={uid()} />'
const createSeparator = _ => '<Separator key={uid()} />'
const genElements = (totalSize, progress) => {
const splitEls = R.splitEvery(3, R.concat(
R.map(createCircle, R.range(0, progress)),
R.map(createCheckBox, R.range(progress, totalSize))
))
const firstSplitGroup = splitEls[0]
const remainingSplitGroups = R.tail(splitEls)
// create a list of separators matching the number of elements in remainingSplitGroups
const separators = R.map(createSeparator, R.range(0, remainingSplitGroups.length))
return R.concat(
// keep the first split group as is
firstSplitGroup,
// prepend a separator to each of the remaining split groups
R.unnest(R.zipWith(R.prepend, separators, remainingSplitGroups))
)
}
console.log(genElements(18, 7))
<script src="//cdnjs.cloudflare.com/ajax/libs/ramda/0.25.0/ramda.min.js"></script>