You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用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):
    1. 第一个对象14.99*18=269.82,未超阈值,直接加入第一个结果的items
    2. 第二个对象24*18=432,与第一个对象总和为701.82,超过阈值,因此只取该对象的17个数量,此时总和为269.82+24*17=677.82,符合要求
    3. 剩余的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:计算需要拆分的结果对象总数
  • 后续分组合并逻辑未完成,无法正确将拆分后的单数量对象合并回原结构,并按阈值分组

完整实现方案

实现思路

  1. 使用递归处理每个输入对象,逐步填充当前结果组,直到达到阈值
  2. 对每个对象,计算能加入当前组的最大数量,剩余数量作为新的待处理对象
  3. 当当前组无法容纳任何数量的当前对象时,新建结果组

完整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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.17 21:58:10