使用 Ramda 过滤每个内部 属性 数组
Filter each inner property arrays with Ramda
我有一个这样的对象:
const arrays = {
one: [[1, 33, 41], [2, 0, 27], [3, 7, 9], [4, 1, 3]],
two: [[1, 77, 2], [2, 6, 3], [3, 0, 0], [4, 55, 3]],
three: [[1, 4, 6], [2, 0, 0], [3, 5, 6], [4, 0, 0]],
};
如您所见,每个 第一个数字 是相等的:
1 每个第一个 内部数组
每秒2 内部数组
3 每三个 内部数组
等...
我想根据每个数组的第一个数字过滤
和一些比较器编号,例如[3]
如果我们有一个过滤器编号[3](小于或等于3),
想要的结果是:
const arrays = {
one: [[1,33,41], [2,0,27], [3,7,9]],
two: [[1,77,2], [2,6,3], [3,0,0]],
three: [[1,4,6], [2,0,0], [3,5,6]],
};
因为内部数组的所有第一个数字都小于或等于3。
以 4,5... 开头的数组将被忽略。
ramda 有什么方法可以实现这个功能?
我知道您想使用 Ramda,这不是使用该库的解决方案,但可以实现相同的效果。您可以通过将第一个数组值 a[0]
与传递给函数的 maxVal
进行比较来创建一个对象 from entries
filtered
。
const arrays = {
one: [[1, 33, 41], [2, 0, 27], [3, 7, 9], [4, 1, 3]],
two: [[1, 77, 2], [2, 6, 3], [3, 0, 0], [4, 55, 3]],
three: [[1, 4, 6], [2, 0, 0], [3, 5, 6], [4, 0, 0]],
};
const filterArrays = (arsObj, maxVal) => {
return Object.fromEntries(Object.entries(arsObj).map(([k, v]) => {
return [k, v.filter((a) => a[0] <= maxVal)];
}));
}
const result = filterArrays(arrays, 3);
console.log(result);
我喜欢 Ramda 的 map
函数,因为它可以遍历对象的属性(因此避免了 Object.fromEntries
& Object.entries
)并对每个对象应用一个函数。该函数是 filter
,它将内部数组作为参数。赋予filter
的功能本身就是gte
和head
的组合;获取数组的第一个元素并将其与 3:
进行比较
const arrays =
{ one: [[1, 33, 41], [2, 0, 27], [3, 7, 9], [4, 1, 3]]
, two: [[1, 77, 2], [2, 6, 3], [3, 0, 0], [4, 55, 3]]
, three: [[1, 4, 6], [2, 0, 0], [3, 5, 6], [4, 0, 0]] };
map(filter(compose(gte(3), head)), arrays);
// ^ ^ ^ ^ ^
// A B C D E
//=> { one: [[ 1, 33, 41], [2, 0, 27], [3, 7, 9]]
//=> , two: [[ 1, 77, 2], [2, 6, 3], [3, 0, 0]]
//=> , three: [[ 1, 4, 6], [2, 0, 0], [3, 5, 6]] }
- 映射每个 属性 (A);每个数组都传递给 filter (B)
- 每个内部数组被传递给compose (C)
- 取每个内部数组的头部(E)与3比较(D)
Scott Christopher 在评论中正确地指出 gte
在部分应用时可能会造成混淆。事实上,整个组合可以用这个简单的 lambda 代替:([x]) => x <= 3
.
我也喜欢的替代方案:
map(filter(([x]) => x <= 3), arrays);
我完全赞同@customcommander 的方法,
只是想补充一点,您也可以将 numerical indexes
传递给 R.propSatisfies
。
const headIs3OrBelow = R.propSatisfies(R.gte(3), 0);
const fn = R.map(R.filter(headIs3OrBelow));
// ===
const data = {
one: [[1, 33, 41], [2, 0, 27], [3, 7, 9], [4, 1, 3]],
two: [[1, 77, 2], [2, 6, 3], [3, 0, 0], [4, 55, 3]],
three: [[1, 4, 6], [2, 0, 0], [3, 5, 6], [4, 0, 0]],
};
console.log(
fn(data),
);
<script src="https://cdnjs.cloudflare.com/ajax/libs/ramda/0.27.1/ramda.js" integrity="sha512-3sdB9mAxNh2MIo6YkY05uY1qjkywAlDfCf5u1cSotv6k9CZUSyHVf4BJSpTYgla+YHLaHG8LUpqV7MHctlYzlw==" crossorigin="anonymous" referrerpolicy="no-referrer"></script>
也同意 gte
和其他类似的方法很难阅读,因为它们有点像 is 3 gte than x
一样向后读......在 Haskell 中你可以这样做:
3 `gte` x
普通方法:
const headIs3OrBelow = ([head]) => head <= 3;
const fn = (data) => Object.entries(data).reduce(
(res, [k, lists]) => ({ ...res, [k]: lists.filter(headIs3OrBelow) }),
{},
);
// ===
const data = {
one: [[1, 33, 41], [2, 0, 27], [3, 7, 9], [4, 1, 3]],
two: [[1, 77, 2], [2, 6, 3], [3, 0, 0], [4, 55, 3]],
three: [[1, 4, 6], [2, 0, 0], [3, 5, 6], [4, 0, 0]],
};
console.log(
fn(data),
);
我有一个这样的对象:
const arrays = {
one: [[1, 33, 41], [2, 0, 27], [3, 7, 9], [4, 1, 3]],
two: [[1, 77, 2], [2, 6, 3], [3, 0, 0], [4, 55, 3]],
three: [[1, 4, 6], [2, 0, 0], [3, 5, 6], [4, 0, 0]],
};
如您所见,每个 第一个数字 是相等的:
1 每个第一个 内部数组
每秒2 内部数组
3 每三个 内部数组
等...
我想根据每个数组的第一个数字过滤
和一些比较器编号,例如[3]
如果我们有一个过滤器编号[3](小于或等于3),
想要的结果是:
const arrays = {
one: [[1,33,41], [2,0,27], [3,7,9]],
two: [[1,77,2], [2,6,3], [3,0,0]],
three: [[1,4,6], [2,0,0], [3,5,6]],
};
因为内部数组的所有第一个数字都小于或等于3。 以 4,5... 开头的数组将被忽略。
ramda 有什么方法可以实现这个功能?
我知道您想使用 Ramda,这不是使用该库的解决方案,但可以实现相同的效果。您可以通过将第一个数组值 a[0]
与传递给函数的 maxVal
进行比较来创建一个对象 from entries
filtered
。
const arrays = {
one: [[1, 33, 41], [2, 0, 27], [3, 7, 9], [4, 1, 3]],
two: [[1, 77, 2], [2, 6, 3], [3, 0, 0], [4, 55, 3]],
three: [[1, 4, 6], [2, 0, 0], [3, 5, 6], [4, 0, 0]],
};
const filterArrays = (arsObj, maxVal) => {
return Object.fromEntries(Object.entries(arsObj).map(([k, v]) => {
return [k, v.filter((a) => a[0] <= maxVal)];
}));
}
const result = filterArrays(arrays, 3);
console.log(result);
我喜欢 Ramda 的 map
函数,因为它可以遍历对象的属性(因此避免了 Object.fromEntries
& Object.entries
)并对每个对象应用一个函数。该函数是 filter
,它将内部数组作为参数。赋予filter
的功能本身就是gte
和head
的组合;获取数组的第一个元素并将其与 3:
const arrays =
{ one: [[1, 33, 41], [2, 0, 27], [3, 7, 9], [4, 1, 3]]
, two: [[1, 77, 2], [2, 6, 3], [3, 0, 0], [4, 55, 3]]
, three: [[1, 4, 6], [2, 0, 0], [3, 5, 6], [4, 0, 0]] };
map(filter(compose(gte(3), head)), arrays);
// ^ ^ ^ ^ ^
// A B C D E
//=> { one: [[ 1, 33, 41], [2, 0, 27], [3, 7, 9]]
//=> , two: [[ 1, 77, 2], [2, 6, 3], [3, 0, 0]]
//=> , three: [[ 1, 4, 6], [2, 0, 0], [3, 5, 6]] }
- 映射每个 属性 (A);每个数组都传递给 filter (B)
- 每个内部数组被传递给compose (C)
- 取每个内部数组的头部(E)与3比较(D)
Scott Christopher 在评论中正确地指出 gte
在部分应用时可能会造成混淆。事实上,整个组合可以用这个简单的 lambda 代替:([x]) => x <= 3
.
我也喜欢的替代方案:
map(filter(([x]) => x <= 3), arrays);
我完全赞同@customcommander 的方法,
只是想补充一点,您也可以将 numerical indexes
传递给 R.propSatisfies
。
const headIs3OrBelow = R.propSatisfies(R.gte(3), 0);
const fn = R.map(R.filter(headIs3OrBelow));
// ===
const data = {
one: [[1, 33, 41], [2, 0, 27], [3, 7, 9], [4, 1, 3]],
two: [[1, 77, 2], [2, 6, 3], [3, 0, 0], [4, 55, 3]],
three: [[1, 4, 6], [2, 0, 0], [3, 5, 6], [4, 0, 0]],
};
console.log(
fn(data),
);
<script src="https://cdnjs.cloudflare.com/ajax/libs/ramda/0.27.1/ramda.js" integrity="sha512-3sdB9mAxNh2MIo6YkY05uY1qjkywAlDfCf5u1cSotv6k9CZUSyHVf4BJSpTYgla+YHLaHG8LUpqV7MHctlYzlw==" crossorigin="anonymous" referrerpolicy="no-referrer"></script>
也同意 gte
和其他类似的方法很难阅读,因为它们有点像 is 3 gte than x
一样向后读......在 Haskell 中你可以这样做:
3 `gte` x
普通方法:
const headIs3OrBelow = ([head]) => head <= 3;
const fn = (data) => Object.entries(data).reduce(
(res, [k, lists]) => ({ ...res, [k]: lists.filter(headIs3OrBelow) }),
{},
);
// ===
const data = {
one: [[1, 33, 41], [2, 0, 27], [3, 7, 9], [4, 1, 3]],
two: [[1, 77, 2], [2, 6, 3], [3, 0, 0], [4, 55, 3]],
three: [[1, 4, 6], [2, 0, 0], [3, 5, 6], [4, 0, 0]],
};
console.log(
fn(data),
);