如何检查对象数组是否是其他数组的子集
how to check whether object array is subset of other array
我需要检查 arr1 是否是 arr2 的子集,前提是两个元素的 ID 相等。
arr1 = [{id:1, value:8}, {id: 2, value: 9};
arr2 = [{id: 1, category: 'a1'}, {id: 2, category: 'a2'}, {id: 3, category: 'a3'}]
我可以用普通的 JS 来完成。但我无法对 Ramda 做同样的事情。我的 ramda 解决方案导致错误
core.js:6456 ERROR TypeError: g.call is not a function
Ramda 解决方案
export const isSubset = (arr: Identifier[]) => all(
compose(
isNotNullOrEmpty,
filter(propEq('id', identity), arr),
prop('id')
)
);
export const isNilOrEmpty = either(isNil, isEmpty);
export const isNotNullOrEmpty = compose(not, isNilOrEmpty);
isSubsetOfInputIdentifiers(arr2)(arr1))
纯 Js 解决方案
arr1.every(
(identifier) =>
arr2?.findIndex(
(identifier1) =>
identifier1.id === identifier.id
) >= 0
)
我只需要使用 ramda 来实现它。我做错了什么?
尽管 Ramda 不提供任何 isSubset
功能,但您可以使用必要的工具自行编写一个简单的版本:
const isSubset = compose (isEmpty, differenceWith (eqProps ('id')))
const arr1 = [{id:1, value:8}, {id: 2, value: 9}];
const arr2 = [{id: 1, category: 'a1'}, {id: 2, category: 'a2'}, {id: 3, category: 'a3'}]
const arr3 = [{id:1, value:8}, {id: 5, value: 11}];
console .log (isSubset (arr1, arr2))
console .log (isSubset (arr3, arr2))
<script src="//cdnjs.cloudflare.com/ajax/libs/ramda/0.27.1/ramda.min.js"></script>
<script> const {compose, isEmpty, differenceWith, eqProps} = R </script>
此处,eqProps
takes a property name and returns a predicate function which reports whether the two supplied parameters have the same value for that property. differenceWith
采用报告两个值是否相等的谓词函数和 returns 接受两个列表的二元函数,并返回第二个参数不在第一个参数中的所有元素根据那个谓词。
我们使用 compose
, with an obvious isEmpty
组合这些,我们得到一个相当紧凑的 isSubset
。
请注意,这比
等 vanilla JS 版本效率低
const isSubset = (xs, ys) =>
xs .every (x => ys .findIndex (y => x .id == y .id) > -1)
因为我们遍历了第一个集合的所有元素,即使我们发现一个早期的元素不包括在内。
如果您有兴趣,我们绝对可以使用一些相同的工具编写最后的 Ramda 版本。但只有当上面的 isSubset
表明存在真正的性能问题时,我才会打扰。
我需要检查 arr1 是否是 arr2 的子集,前提是两个元素的 ID 相等。
arr1 = [{id:1, value:8}, {id: 2, value: 9};
arr2 = [{id: 1, category: 'a1'}, {id: 2, category: 'a2'}, {id: 3, category: 'a3'}]
我可以用普通的 JS 来完成。但我无法对 Ramda 做同样的事情。我的 ramda 解决方案导致错误
core.js:6456 ERROR TypeError: g.call is not a function
Ramda 解决方案
export const isSubset = (arr: Identifier[]) => all(
compose(
isNotNullOrEmpty,
filter(propEq('id', identity), arr),
prop('id')
)
);
export const isNilOrEmpty = either(isNil, isEmpty);
export const isNotNullOrEmpty = compose(not, isNilOrEmpty);
isSubsetOfInputIdentifiers(arr2)(arr1))
纯 Js 解决方案
arr1.every(
(identifier) =>
arr2?.findIndex(
(identifier1) =>
identifier1.id === identifier.id
) >= 0
)
我只需要使用 ramda 来实现它。我做错了什么?
尽管 Ramda 不提供任何 isSubset
功能,但您可以使用必要的工具自行编写一个简单的版本:
const isSubset = compose (isEmpty, differenceWith (eqProps ('id')))
const arr1 = [{id:1, value:8}, {id: 2, value: 9}];
const arr2 = [{id: 1, category: 'a1'}, {id: 2, category: 'a2'}, {id: 3, category: 'a3'}]
const arr3 = [{id:1, value:8}, {id: 5, value: 11}];
console .log (isSubset (arr1, arr2))
console .log (isSubset (arr3, arr2))
<script src="//cdnjs.cloudflare.com/ajax/libs/ramda/0.27.1/ramda.min.js"></script>
<script> const {compose, isEmpty, differenceWith, eqProps} = R </script>
此处,eqProps
takes a property name and returns a predicate function which reports whether the two supplied parameters have the same value for that property. differenceWith
采用报告两个值是否相等的谓词函数和 returns 接受两个列表的二元函数,并返回第二个参数不在第一个参数中的所有元素根据那个谓词。
我们使用 compose
, with an obvious isEmpty
组合这些,我们得到一个相当紧凑的 isSubset
。
请注意,这比
等 vanilla JS 版本效率低const isSubset = (xs, ys) =>
xs .every (x => ys .findIndex (y => x .id == y .id) > -1)
因为我们遍历了第一个集合的所有元素,即使我们发现一个早期的元素不包括在内。
如果您有兴趣,我们绝对可以使用一些相同的工具编写最后的 Ramda 版本。但只有当上面的 isSubset
表明存在真正的性能问题时,我才会打扰。