如何用DWL实现对象数组按总价阈值动态拆分
按阈值拆分对象数组的DataWeave实现问题
输入数据
[ { "number": "000001", "price": 14.99, "qty": 18, "line": "3" }, { "number": "000003", "price": 24.0, "qty": 18, "line": "3" }, { "number": "000004", "price": 18.0, "qty": 18, "line": "3" } ]
拆分规则
- 将原数组拆分为多个结果对象,每个结果对象的
items中所有元素的(price * qty)总和不得超过指定阈值 - 处理逻辑示例(阈值设为700):
- 第一个对象
14.99*18=269.82,未超阈值,直接加入第一个结果的items - 第二个对象
24*18=432,与第一个对象总和为701.82,超过阈值,因此只取该对象的17个数量,此时总和为269.82+24*17=677.82,符合要求 - 剩余的1个第二个对象,与第三个对象
18*18=324总和为24+324=348,未超阈值,组成第二个结果的items
- 第一个对象
预期输出
[ { "object": 1, "total": 677.82, "items": [ { "number": "000001", "price": 14.99, "qty": 18, "line": "3" }, { "number": "000003", "price": 24.0, "qty": 17, "line": "3" } ] }, { "object": 2, "total": 348.00, "items": [ { "number": "000003", "price": 24.0, "qty": 1, "line": "3" }, { "number": "000004", "price": 18.0, "qty": 18, "line": "3" } ] } ]
结果字段说明
"object":结果对象的索引编号"total":对应items中所有元素(price * qty)的总和"items":按规则拆分后的子对象数组
注:若
maxTotal提高到1100,结果不变;若降低到200,最终会拆分为5个结果对象。
当前未完成的DataWeave代码
%dw 2.0 import * from dw::core::Arrays output application/json var inputArray = [ { "number": "000001", "price": 14.99, "qty": 18, "line": "3" }, { "number": "000003", "price": 24.0, "qty": 18, "line": "3" }, { "number": "000004", "price": 18.0, "qty": 18, "line": "3" } ] var maxTotal = 700 var listOfItems = flatten(inputArray map (itm, idx) -> do { var result = 1 to itm.qty as Number map (i) -> ({ "number": itm.number, "price": itm.price, "qty": 1, "line": itm.line }) --- result }) var divideTo = ((sum(listOfItems.price) / maxTotal) as String {format: "0", roundMode: "UP"}) as Number --- 1 to divideTo map (itm, idx) -> do { var total = 0 var items = {} --- { object: (idx + 1), total: total, items: items } }
代码说明
listOfItems:将原对象按qty拆分为多个单数量的对象数组divideTo:计算需要拆分的结果对象总数- 后续分组合并逻辑未完成,无法正确将拆分后的单数量对象合并回原结构,并按阈值分组
完整实现方案
实现思路
- 使用递归处理每个输入对象,逐步填充当前结果组,直到达到阈值
- 对每个对象,计算能加入当前组的最大数量,剩余数量作为新的待处理对象
- 当当前组无法容纳任何数量的当前对象时,新建结果组
完整DataWeave代码
%dw 2.0 import * from dw::core::Arrays output application/json var inputArray = [ { "number": "000001", "price": 14.99, "qty": 18, "line": "3" }, { "number": "000003", "price": 24.0, "qty": 18, "line": "3" }, { "number": "000004", "price": 18.0, "qty": 18, "line": "3" } ] var maxTotal = 700 // 递归函数:处理待处理对象列表,生成结果组 fun processItems(remainingItems: Array<{}>, currentGroups: Array<{}>): Array<{}> = if (isEmpty(remainingItems)) currentGroups else do { var currentItem = remainingItems[0] var currentItemUnitTotal = currentItem.price var currentGroup = if (isEmpty(currentGroups)) {} else currentGroups[-1] var currentGroupTotal = currentGroup.total default 0 var availableSpace = maxTotal - currentGroupTotal // 计算当前对象能加入当前组的最大数量 var maxPossibleQty = floor(availableSpace / currentItemUnitTotal) if (maxPossibleQty > 0) do { var qtyToAdd = min(maxPossibleQty, currentItem.qty) var newTotal = currentGroupTotal + (currentItemUnitTotal * qtyToAdd) var updatedItem = currentItem update { case .qty -> qtyToAdd } var remainingQty = currentItem.qty - qtyToAdd // 更新当前组或新建组 var updatedGroups = if (isEmpty(currentGroups)) [{ object: sizeOf(currentGroups) + 1, total: newTotal, items: [updatedItem] }] else currentGroups update { case last at -1 -> last update { case .total -> newTotal case .items -> last.items << updatedItem } } // 处理剩余数量的当前对象或下一个对象 var newRemainingItems = if (remainingQty > 0) (currentItem update { case .qty -> remainingQty }) ++ remainingItems[1 to -1] else remainingItems[1 to -1] --- processItems(newRemainingItems, updatedGroups) } else do { // 当前组无法容纳当前对象,新建组 var newGroup = { object: sizeOf(currentGroups) + 1, total: currentItemUnitTotal * currentItem.qty, items: [currentItem] } --- processItems(remainingItems[1 to -1], currentGroups << newGroup) } } --- processItems(inputArray, [])
新增输出示例(阈值≥1000时)
[ { "object": 1, "total": 269.82, "items": [ { "number": "000001", "price": 14.99, "qty": 18, "line": "3" } ] }, { "object": 2, "total": 432, "items": [ { "number": "000003", "price": 24, "qty": 18, "line": "3" } ] }, { "object": 3, "total": 324, "items": [ { "number": "000004", "price": 18, "qty": 18, "line": "3" } ] } ]
内容的提问来源于stack exchange,提问作者Jesus Abraham Felix González
相关产品推荐
相关产品推荐

