使用ramda根据序列逻辑有条件地拆分数组
Conditionally split array based on sequence logic using ramda
我有一组照片,每张照片都有一个 aspectRatio
。我想根据 aspectRatio
.
将数组拆分为不同长度的较小数组
const photos = [
{ fluid: { aspectRatio: 1.5 } },
{ fluid: { aspectRatio: 1.5 } },
{ fluid: { aspectRatio: 0.67 } },
{ fluid: { aspectRatio: 0.67 } },
{ fluid: { aspectRatio: 0.67 } },
{ fluid: { aspectRatio: 0.67 } },
{ fluid: { aspectRatio: 1.5 } },
{ fluid: { aspectRatio: 1.5 } },
{ fluid: { aspectRatio: 0.67 } }
]
在这种情况下,我想默认每2项拆分数组,然后当连续3项aspectRatio < 1
时拆分为3项。
我想留下的是:
const result = [
[
{ fluid: { aspectRatio: 1.5 } },
{ fluid: { aspectRatio: 1.5 } }
],
[
{ fluid: { aspectRatio: 0.67 } },
{ fluid: { aspectRatio: 0.67 } },
{ fluid: { aspectRatio: 0.67 } },
],
[
{ fluid: { aspectRatio: 0.67 } },
{ fluid: { aspectRatio: 1.5 } }
],
[
{ fluid: { aspectRatio: 1.5 } },
{ fluid: { aspectRatio: 0.67 } }
],
]
我研究过使用 splitWhen
,但它似乎只适用于当前项目,无法在数组中向前看。
您可以使用 Array.reduce()
迭代数组,并根据您提供的规则向累加器添加一个新的子数组。始终将当前项推入最后一个子数组:
const photos = [{"fluid":{"aspectRatio":1.5}},{"fluid":{"aspectRatio":1.5}}, {"fluid":{"aspectRatio":1.5}},{"fluid":{"aspectRatio":0.67}},{"fluid":{"aspectRatio":0.67}},{"fluid":{"aspectRatio":0.67}},{"fluid":{"aspectRatio":0.67}},{"fluid":{"aspectRatio":1.5}},{"fluid":{"aspectRatio":1.5}},{"fluid":{"aspectRatio":0.67}}]
const allAspectsUnder1 = arr => arr.every(o => o.fluid.aspectRatio < 1)
const result = photos.reduce((r, o) => {
const last = r[r.length - 1]
if (!last ||
last.length === 3 ||
(last.length === 2 && !allAspectsUnder1(last))
) r.push([])
r[r.length - 1].push(o)
return r
}, [])
console.log(result)
这与 Ramda 中的等效思想:
const { pipe, length, equals, allPass, any, pathSatisfies, lt, last, anyPass, isNil, reduce, ifElse, init } = R
const lengthEquals = len => pipe(length, equals(len))
const length2AndLargeAspects = allPass([
lengthEquals(2),
any(pathSatisfies(lt(1), ['fluid', 'aspectRatio'])),
])
const shouldAddSub = pipe(
last,
anyPass([
isNil,
length2AndLargeAspects,
lengthEquals(3),
])
)
const fn = reduce(ifElse(
shouldAddSub,
(a, o) => [...a, [o]],
(a, o) => [...init(a), [...last(a), o]],
), [])
const photos = [{"fluid":{"aspectRatio":1.5}},{"fluid":{"aspectRatio":1.5}}, {"fluid":{"aspectRatio":1.5}},{"fluid":{"aspectRatio":0.67}},{"fluid":{"aspectRatio":0.67}},{"fluid":{"aspectRatio":0.67}},{"fluid":{"aspectRatio":0.67}},{"fluid":{"aspectRatio":1.5}},{"fluid":{"aspectRatio":1.5}},{"fluid":{"aspectRatio":0.67}}]
const result = fn(photos)
console.log(result)
<script src="https://cdnjs.cloudflare.com/ajax/libs/ramda/0.26.1/ramda.js"></script>
我认为 Ramda 在这方面没有任何帮助。我的想法是递归地执行此操作:
const group = (ps, rs = []) => ps.length == 0
? rs
: ps.length < 3
? rs.concat([ps])
: ps.slice(0, 3).every(p => p.fluid.aspectRatio < 1)
? group(ps.slice(3), rs.concat([ps.slice(0, 3)]))
: group(ps.slice(2), rs.concat([ps.slice(0, 2)]))
const photos = [{fluid: {aspectRatio: 1.5}}, {fluid: {aspectRatio: 1.5}}, {fluid: {aspectRatio: 0.67}}, {fluid: {aspectRatio: 0.67}}, {fluid: {aspectRatio: 0.67}}, {fluid: {aspectRatio: 0.67}}, {fluid: {aspectRatio: 1.5}}, {fluid: {aspectRatio: 1.5}}, {fluid: {aspectRatio: 0.67}}]
console.log(group(photos))
使用简单的 do/while
循环。按 3 对子数组进行切片并检查是否有大于 1 的数组,如果有
则返回 2
let res=[], sIdx = 0;
do {
const arr = photos.slice(sIdx, sIdx + 3);
if(arr.length > 2 && arr.some(({ fluid:{aspectRatio}}) => aspectRatio >= 1 ) ){
arr.pop();
}
res.push(arr);
sIdx += arr.length;
} while ( sIdx < photos.length)
console.log(res)
.as-console-wrapper { max-height: 100%!important;}
<script>
const photos = [
{ fluid: { aspectRatio: 1.5 } },
{ fluid: { aspectRatio: 1.5 } },
{ fluid: { aspectRatio: 0.67 } },
{ fluid: { aspectRatio: 0.67 } },
{ fluid: { aspectRatio: 0.67 } },
{ fluid: { aspectRatio: 0.67 } },
{ fluid: { aspectRatio: 1.5 } },
{ fluid: { aspectRatio: 1.5 } },
{ fluid: { aspectRatio: 0.67 } }
]
</script>
我有一组照片,每张照片都有一个 aspectRatio
。我想根据 aspectRatio
.
const photos = [
{ fluid: { aspectRatio: 1.5 } },
{ fluid: { aspectRatio: 1.5 } },
{ fluid: { aspectRatio: 0.67 } },
{ fluid: { aspectRatio: 0.67 } },
{ fluid: { aspectRatio: 0.67 } },
{ fluid: { aspectRatio: 0.67 } },
{ fluid: { aspectRatio: 1.5 } },
{ fluid: { aspectRatio: 1.5 } },
{ fluid: { aspectRatio: 0.67 } }
]
在这种情况下,我想默认每2项拆分数组,然后当连续3项aspectRatio < 1
时拆分为3项。
我想留下的是:
const result = [
[
{ fluid: { aspectRatio: 1.5 } },
{ fluid: { aspectRatio: 1.5 } }
],
[
{ fluid: { aspectRatio: 0.67 } },
{ fluid: { aspectRatio: 0.67 } },
{ fluid: { aspectRatio: 0.67 } },
],
[
{ fluid: { aspectRatio: 0.67 } },
{ fluid: { aspectRatio: 1.5 } }
],
[
{ fluid: { aspectRatio: 1.5 } },
{ fluid: { aspectRatio: 0.67 } }
],
]
我研究过使用 splitWhen
,但它似乎只适用于当前项目,无法在数组中向前看。
您可以使用 Array.reduce()
迭代数组,并根据您提供的规则向累加器添加一个新的子数组。始终将当前项推入最后一个子数组:
const photos = [{"fluid":{"aspectRatio":1.5}},{"fluid":{"aspectRatio":1.5}}, {"fluid":{"aspectRatio":1.5}},{"fluid":{"aspectRatio":0.67}},{"fluid":{"aspectRatio":0.67}},{"fluid":{"aspectRatio":0.67}},{"fluid":{"aspectRatio":0.67}},{"fluid":{"aspectRatio":1.5}},{"fluid":{"aspectRatio":1.5}},{"fluid":{"aspectRatio":0.67}}]
const allAspectsUnder1 = arr => arr.every(o => o.fluid.aspectRatio < 1)
const result = photos.reduce((r, o) => {
const last = r[r.length - 1]
if (!last ||
last.length === 3 ||
(last.length === 2 && !allAspectsUnder1(last))
) r.push([])
r[r.length - 1].push(o)
return r
}, [])
console.log(result)
这与 Ramda 中的等效思想:
const { pipe, length, equals, allPass, any, pathSatisfies, lt, last, anyPass, isNil, reduce, ifElse, init } = R
const lengthEquals = len => pipe(length, equals(len))
const length2AndLargeAspects = allPass([
lengthEquals(2),
any(pathSatisfies(lt(1), ['fluid', 'aspectRatio'])),
])
const shouldAddSub = pipe(
last,
anyPass([
isNil,
length2AndLargeAspects,
lengthEquals(3),
])
)
const fn = reduce(ifElse(
shouldAddSub,
(a, o) => [...a, [o]],
(a, o) => [...init(a), [...last(a), o]],
), [])
const photos = [{"fluid":{"aspectRatio":1.5}},{"fluid":{"aspectRatio":1.5}}, {"fluid":{"aspectRatio":1.5}},{"fluid":{"aspectRatio":0.67}},{"fluid":{"aspectRatio":0.67}},{"fluid":{"aspectRatio":0.67}},{"fluid":{"aspectRatio":0.67}},{"fluid":{"aspectRatio":1.5}},{"fluid":{"aspectRatio":1.5}},{"fluid":{"aspectRatio":0.67}}]
const result = fn(photos)
console.log(result)
<script src="https://cdnjs.cloudflare.com/ajax/libs/ramda/0.26.1/ramda.js"></script>
我认为 Ramda 在这方面没有任何帮助。我的想法是递归地执行此操作:
const group = (ps, rs = []) => ps.length == 0
? rs
: ps.length < 3
? rs.concat([ps])
: ps.slice(0, 3).every(p => p.fluid.aspectRatio < 1)
? group(ps.slice(3), rs.concat([ps.slice(0, 3)]))
: group(ps.slice(2), rs.concat([ps.slice(0, 2)]))
const photos = [{fluid: {aspectRatio: 1.5}}, {fluid: {aspectRatio: 1.5}}, {fluid: {aspectRatio: 0.67}}, {fluid: {aspectRatio: 0.67}}, {fluid: {aspectRatio: 0.67}}, {fluid: {aspectRatio: 0.67}}, {fluid: {aspectRatio: 1.5}}, {fluid: {aspectRatio: 1.5}}, {fluid: {aspectRatio: 0.67}}]
console.log(group(photos))
使用简单的 do/while
循环。按 3 对子数组进行切片并检查是否有大于 1 的数组,如果有
let res=[], sIdx = 0;
do {
const arr = photos.slice(sIdx, sIdx + 3);
if(arr.length > 2 && arr.some(({ fluid:{aspectRatio}}) => aspectRatio >= 1 ) ){
arr.pop();
}
res.push(arr);
sIdx += arr.length;
} while ( sIdx < photos.length)
console.log(res)
.as-console-wrapper { max-height: 100%!important;}
<script>
const photos = [
{ fluid: { aspectRatio: 1.5 } },
{ fluid: { aspectRatio: 1.5 } },
{ fluid: { aspectRatio: 0.67 } },
{ fluid: { aspectRatio: 0.67 } },
{ fluid: { aspectRatio: 0.67 } },
{ fluid: { aspectRatio: 0.67 } },
{ fluid: { aspectRatio: 1.5 } },
{ fluid: { aspectRatio: 1.5 } },
{ fluid: { aspectRatio: 0.67 } }
]
</script>