【问题标题】:Reshape a array to object with jq使用 jq 将数组重塑为对象
【发布时间】:2021-01-31 00:25:02
【问题描述】:

我正在学习 jq 的高级概念。我用查尔斯卓别林的一些电影制作了一个带有数组的小 json……嗯,这个数组在 json 中:

[
    {
        "title": "The Great Dictator",
        "year": 1940,
        "country": "USA",
        "genre": "political satire"
    },
    {
        "title": "Modern Times ",
        "year": 1936,
        "country": "USA",
        "genre": "comedy"
    },
    {
        "title": "The Gold Rush",
        "year": 1925,
        "country": "USA",
        "genre": "comedy"
    },
    {
        "title": "The Kid",
        "year": 1921,
        "country": "USA",
        "genre": "drama"
    }
]

我想将类型转换或重塑为一个对象,其中以流派为键,电影列表为数组(喜剧在数组中只有两个元素):

{
    "comedy": [
        {
            "title": "Modern Times ",
            "year": 1936,
            "country": "USA"
        },
        {
            "title": "The Gold Rush",
            "year": 1925,
            "country": "USA"
        }
    ],
    "political satire":  [
        {
            "title": "The Great Dictator",
            "year": 1940,
            "country": "USA"
        }
    ],
    "drama": [
        {
            "title": "The Kid",
            "year": 1921,
            "country": "USA"
        }
    ]
}

但我做不到。我尝试第一步创建一个以流派和 foo 字符串为 var 的对象,但它失败了:cat c.json | jq '{.[] | (.genre): "foo" ]}'

【问题讨论】:

  • 我发现这个问题stackoverflow.com/questions/42427725/…cat c.json | jq 'INDEX(.genre)' 喜剧条目只有元素。
  • cat c.json | jq '[.[] | {(.genre): [.]}] | add' 和之前的评论一样...喜剧只有一部电影。

标签: json jq


【解决方案1】:

可以分三行完成:

[group_by(.genre)[]
 | {(.[0].genre): map_values(del(.genre))}] 
| add 

aggregate_by/3

这里相关的通用抽象是:

def aggregate_by(s; f; g):
  reduce s as $x  (null; .[$x|f] += [$x|g]);

这使得解决方案可以直接写成:

aggregate_by(.[]; .genre; del(.genre))

【讨论】:

    【解决方案2】:

    我找到了:

    $ cat c.json | jq '
      group_by(.genre)
      | map({"genre": .[0].genre, 
             "film": map(. | del(.genre))})
      | [ .[] | {(.genre): .film}]
      | add'
    {
      "comedy": [
        {
          "title": "Modern Times ",
          "year": 1936,
          "country": "USA"
        },
        {
          "title": "The Gold Rush",
          "year": 1925,
          "country": "USA"
        }
      ],
      "drama": [
        {
          "title": "The Kid",
          "year": 1921,
          "country": "USA"
        }
      ],
      "political satire": [
        {
          "title": "The Great Dictator",
          "year": 1940,
          "country": "USA"
        }
      ]
    }
    

    也许它不是最好的,因为我认为有很多步骤......但它运行。

    【讨论】:

      【解决方案3】:

      您可以在页面you linked to 上使用 Jeff Mercado 答案的修改版本。

      jq 'reduce .[] as $i ({}; .[$i.genre] += [$i])'
      

      根据需要对对象进行分组,但保留类型键值对。你可以像这样删除它们。

      jq 'reduce .[] as $i ({}; .[$i.genre] += [$i|del(.genre)])'
      

      真的,这只是 peak 的“通用抽象”的具体版本。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2022-10-07
        • 2023-01-24
        • 1970-01-01
        相关资源
        最近更新 更多