如何在JQ中封装基于父/同级属性的动态条件过滤函数?
解决JQ中基于父/同级属性过滤数组的函数封装问题
咱们先把核心问题掰明白:JQ的函数作用域是封闭的,默认没法直接访问外部的$parent变量,所以要解决这个问题,关键是把父级上下文作为参数传递给函数,同时调整辅助函数的结构,让它能支持动态传入条件和属性。
调整后的辅助函数定义
先修改两个辅助函数,给它们加上父级上下文的参数,同时保留灵活性:
# 新增$parent参数,用来传递父级对象上下文 def getFieldsThatCheckConditionInArray($parent; condition; returnValues): if condition then returnValues else empty end; # 同样新增$parent参数,传递给内部的过滤逻辑 def generateConflictArray(arrayName; $parent; arrayToCheck; conflictToCheck): map( . + { (arrayName): [ arrayToCheck | conflictToCheck($parent) ] } );
符合期望的函数调用方式
现在你可以按预想的方式调用函数,只需要把当前对象作为$parent传递进去即可:
. | generateConflictArray( "conflictsInPeriod"; .; # 这里把当前对象作为父级上下文传入 .events[]; # 定义动态的过滤逻辑,可按需修改条件和返回字段 ($parent) -> getFieldsThatCheckConditionInArray( $parent; # 过滤条件:供应商ID匹配工单,且工单日期前84天(12*7)早于事件结束日期 ($parent.workorder.startDate | dateDaysAgo(12*7)) < .endDate and .vendorId == $parent.workorder.vendorId; # 返回的字段可自定义 { event: .id, workorder_sd: $parent.workorder.startDate[:10], workorder_id: $parent.workorder.id } ) )
关键细节解释
- 父作用域传递:通过把当前对象(
.)作为$parent参数传入generateConflictArray,再传递给getFieldsThatCheckConditionInArray,彻底解决了函数内部无法访问外部父对象的问题。 - 灵活性:现在你可以轻松修改过滤条件(比如换成其他父级属性进行匹配)或者返回的字段,只需要调整调用时的条件和返回值部分就行,不用修改函数本身。
- 空值处理:
getFieldsThatCheckConditionInArray里的else empty保证不匹配的元素不会被加入结果数组,避免出现无效数据。
测试示例数据的输出结果
用你提供的示例数据运行上面的代码,会得到你期望的输出:每个原对象都会新增conflictsInPeriod数组,包含所有符合条件的事件信息,比如:
[ { "storeId": "s2", "storehouseInfo": { "id": "025453", "name": "00211 NW, OR", "maxPallets": 10 }, "workorder": { "id": "w2s2", "startDate": "2019-09-06T10:00:00.000Z", "vendorId": "v2" }, "events": [...], "conflictsInPeriod": [ { "event": "e5", "workorder_sd": "2019-09-06", "workorder_id": "w2s2" }, { "event": "e11", "workorder_sd": "2019-09-06", "workorder_id": "w2s2" }, { "event": "e12", "workorder_sd": "2019-09-06", "workorder_id": "w2s2" } ] } ]
内容的提问来源于stack exchange,提问作者user2835192
相关产品推荐
相关产品推荐

