JQ:使用辅助阵列丰富主阵列

时间:2018-02-28 23:00:37

标签: arrays json match jq

我有两个包含商品价格的数组:

[{"id":"a","p":5},{"id":"b","p":7},{"id":"c","p":8}]

[{"id":"a","p":9},{"id":"b","p":7},{"id":"d","p":4}]

我希望使用辅助数组中的价格来丰富主数组(如果可用)。如果价格尚未更新,则应删除该条目。因此,想要的输出是(" b"因为价格相等而被删除,并且" c"保留):

[{"id":"a","p":5,"c":9},{"id":"c","p":8,"c":null}]

我尝试使用select,但这会删除两个数组中不可用的项目:

echo '$pri' | jq -c --argjson sec '$sec' '.[]|. as {id:$id,p:$c}|{id,p,"c":($sec[]|select(.id==$id and .p!=$c).p)}'

编辑: 高峰的回答让我朝着正确的方向前进。一旦它开始工作,我就进一步改进了它。

更新后的价格始终是一个包含未分类方式的所有项目的数组。我希望在没有真正更新的情况下避免光盘写入。

因此,我已经以字典格式保存了最后的价格响应,如:

wget ... | jq -c 'reduce .[] as $x ({}; .[$x|.id|tostring]=$x)' >lastprices

此步骤转换输入数组

{"id":28460,"price":"1.119","time":"2018-03-05T18:33:43Z","camp":null}
{"id":11438,"price":"1.119","time":"2018-03-05T18:58:26Z","camp":null}
{"id":11627,"price":"1.119","time":"2018-03-05T18:47:45Z","camp":null}
{"id":6905,"price":"1.119","time":"2018-03-05T19:03:59Z","camp":null}

到索引排序的输出数组(字典)

{ "6905"  : { "id":6905,  "price":"1.119", "time":"2018-03-05T19:03:59Z", "camp":null },
  "11438" : { "id":11438, "price":"1.119", "time":"2018-03-05T18:58:26Z", "camp":null },
  "11627" : { "id":11627, "price":"1.119", "time":"2018-03-05T18:47:45Z", "camp":null },
  "28460" : { "id":28460, "price":"1.119", "time":"2018-03-05T18:33:43Z", "camp":null } }

在下一次迭代中,我比较update.time != last.time并仅保留(= select)已更新的项目:

wget ... | jq -c --argfile last lastprices '[.[]|select(.time!=$last[.id|tostring].time)]'

如果比较评估了非空数组I convert it to CSV并将其附加到"数据库" (保存为JSON每次都需要重写整个数组):

echo "$COMPARISON" | jq -rc '(.[0] | keys_unsorted) as $keys | map([.[ $keys[] ]])[]|@csv'>>gasdb.csv

1 个答案:

答案 0 :(得分:0)

要求“如果价格尚未更新,则应删除该条目”。似乎与这个例子不一致,所以下面假设这个例子是明确的。

首先,一个用于生成(快速)查找表的小辅助函数:

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

在下文中,与问题文本一样,$pri引用具有旧价格的数组,$sec引用具有新价格的数组:

($sec|dict(.id)) as $new
| reduce $pri[] as $x ([];
    $new[$x.id] as $y
    | if ($y.p == $x.p) then .
      else . + [$x | (.c = $y.p)]
      end )

结果是给定的。