如何对jq中的映射数组中的值求和?

时间:2015-02-12 17:59:45

标签: json sum key jq

给定以下形式的JSON流:

{ "a": 10, "b": 11 } { "a": 20, "b": 21 } { "a": 30, "b": 31 }

我想对每个对象中的值求和并输出一个对象,即:

{ "a": 60, "b": 63 }

我猜这可能需要将上面的对象列表展平为一个[name, value]对数组,然后使用reduce对值进行求和,但使用{{1}语法的文档很可悲。

3 个答案:

答案 0 :(得分:20)

除非您的jq有inputs,否则您必须使用-s标记来对齐对象。然后你将不得不做相当多的操作:

  1. 每个对象都需要映射到键/值对
  2. 将对平展为单个数组
  3. 按键分组对
  4. 将累积值的每个组映射到单个键/值对
  5. 将对映射回对象
  6. map(to_entries)
        | add
        | group_by(.key)
        | map({
              key: .[0].key,
              value: map(.value) | add
          })
        | from_entries
    

    使用jq 1.5,可以大大改善:你可以放弃啜饮,直接阅读inputs

    $ jq -n '
    reduce (inputs | to_entries[]) as {$key,$value} ({}; .[$key] += $value)
    ' input.json
    

    由于我们只是在每个对象中累积所有值,因此只需运行所有输入的键/值对,并将它们全部添加起来就更容易了。

答案 1 :(得分:5)

另一种很好地说明jq功能的方法是使用名为" sum"的过滤器。定义如下:

def sum(f): reduce .[] as $row (0; . + ($row|f) );

要解决手头的特定问题,可以使用上面提到的-s( - slurp)选项以及表达式:

{"a": sum(.a), "b": sum(.b) }  # (2)

标记为(2)的表达式仅计算两个指定的和,但很容易推广,例如如下:

# Produce an object with the same keys as the first object in the 
# input array, but with values equal to the sum of the corresponding
# values in all the objects.
def sumByKey:
  . as $in
  | reduce (.[0] | keys)[] as $key
    ( {}; . + {($key): ($in | sum(.[$key]))})
;

答案 2 :(得分:3)

在列出GitHub上的所有工件时,我遇到了同样的问题(有关详细信息,请参见here),并希望对其大小求和。

curl https://api.github.com/repos/:owner/:repo/actions/artifacts \
     -H "Accept: application/vnd.github.v3+json" \
     -H "Authorization:  token <your_pat_here>" \
     | jq '.artifacts | map(.size_in_bytes) | add'

输入:

{
  "total_count": 3,
  "artifacts": [
    {
      "id": 0000001,
      "node_id": "MDg6QXJ0aWZhY3QyNzUxNjI1",
      "name": "artifact-1",
      "size_in_bytes": 1,
      "url": "https://api.github.com/repos/:owner/:repo/actions/artifacts/2751625",
      "archive_download_url": "https://api.github.com/repos/:owner/:repo/actions/artifacts/2751625/zip",
      "expired": false,
      "created_at": "2020-03-10T18:21:23Z",
      "updated_at": "2020-03-10T18:21:24Z"
    },
    {
      "id": 0000002,
      "node_id": "MDg6QXJ0aWZhY3QyNzUxNjI0",
      "name": "artifact-2",
      "size_in_bytes": 2,
      "url": "https://api.github.com/repos/:owner/:repo/actions/artifacts/2751624",
      "archive_download_url": "https://api.github.com/repos/:owner/:repo/actions/artifacts/2751624/zip",
      "expired": false,
      "created_at": "2020-03-10T18:21:23Z",
      "updated_at": "2020-03-10T18:21:24Z"
    },
    {
      "id": 0000003,
      "node_id": "MDg6QXJ0aWZhY3QyNzI3NTk1",
      "name": "artifact-3",
      "size_in_bytes": 3,
      "url": "https://api.github.com/repos/docker/mercury-ui/actions/artifacts/2727595",
      "archive_download_url": "https://api.github.com/repos/:owner/:repo/actions/artifacts/2727595/zip",
      "expired": false,
      "created_at": "2020-03-10T08:46:08Z",
      "updated_at": "2020-03-10T08:46:09Z"
    }
  ]
}

输出:

6