如何使用 jq 生成输入中存在的两个数组的笛卡尔积 JSON

How to use jq to produce a cartesian product of two arrays present in the input JSON

我希望能够使用 jq 在输入 JSON 中输出 2 个数组的 'product'... 例如,给定以下输入 JSON:

 {
     "quantities": [
         {
             "product": "A",
             "quantity": 30
         },
         {
             "product": "B",
             "quantity": 10
         }
         ],
     "portions": [
         {
             "customer": "C1",
             "percentage": .6
         },
         {
             "customer": "C2",
             "percentage": .4
         }
     ]
 }

我想生成以下输出(或类似...):

[
    {
     "customer": "C1",
     "quantities": [
         {
             "product": "A",
             "quantity": 18
         },
         {
             "product": "B",
             "quantity": 6
         }
         ]
    },
    {
     "customer": "C2",
     "quantities": [
         {
             "product": "A",
             "quantity": 12
         },
         {
             "product": "B",
             "quantity": 4
         }
         ]
    }
]

换句话说,对于每个部分,使用其百分比值,并将其应用于每个产品数量。给定 2 个数量和 2 个部分应该产生 4 个结果。给定 3 个数量和 2 个部分应该产生 6 个结果,等等...

我尝试使用 foreach 过滤器,但无济于事...

我想这会做你想要的。

[
  .quantities as $q
| .portions[]
| .percentage as $p
| {
    customer,
    quantities: [
       $q[] | .quantity = .quantity * $p
    ]
  }
]

既然你表示你想要笛卡尔积,并且你只给出了样本输出作为你正在寻找的东西的指示,可能值得一提的是可以非常简单地获得笛卡尔积:

 .portions[] + .quantities[]

这会产生如下对象:

{
  "product": "B",
  "quantity": 10,
  "customer": "C2",
  "percentage": 0.4
}

然后您可以使用 reduce 或(效率较低,group_by)以您真正想要的任何形式获取数据。

例如,假设 .customer 始终是一个字符串,我们可以转换 输入请求格式如下:

def add_by(f;g): reduce .[] as $x ({}; .[$x|f] += [$x|g]);

[.quantities[] + .portions[]]
| map( {customer, quantities: {product, quantity: (.quantity * .percentage)}} )
| add_by(.customer; .quantities)
| to_entries
| map( {customer: .key, quantities: .value })