jq 将相同键的值合并到数组中?

jq 将相同键的值合并到数组中?

我有一个 SQL 结果集导出为 JSON,采用数组中 1:1 映射的形式。

例如

[
  {
    "subject": "Accounting",
    "level": "A Level"
  },
  {
    "subject": "Accounting",
    "level": "IB"
  },
  {
    "subject": "Accounting",
    "level": "University"
  },
  {
    "subject": "Accounting",
    "level": "GCSE"
  },
  {
    "subject": "Accounting",
    "level": "Mentoring"
  },
  {
    "subject": "Accounting",
    "level": "13 Plus"
  },
  {
    "subject": "Accounting",
    "level": "11 Plus"
  },
etc.....

我想将各个级别合并为一个主题键,如下所示:

[
   "Accounting": ["A Level", "IB", "University"],
   "Foo": ["Foo Intro", "Foo Basics", "Intermediate Foo"] 
]

笔记:没有匿名对象

我怎样才能用jq实现这个目标?

答案1

给定

$ jq '.' file.json
[
  {
    "subject": "Accounting",
    "level": "A Level"
  },
  {
    "subject": "Foo",
    "level": "IB"
  },
  {
    "subject": "Accounting",
    "level": "University"
  },
  {
    "subject": "Foo",
    "level": "GCSE"
  },
  {
    "subject": "Accounting",
    "level": "Mentoring"
  },
  {
    "subject": "Accounting",
    "level": "13 Plus"
  },
  {
    "subject": "Foo",
    "level": "11 Plus"
  }
]

然后大量借钱使用汇总数据重塑 jq 数组

$ jq 'reduce .[] as $d (null; .[$d.subject] += [$d.level])' file.json 
{
  "Accounting": [
    "A Level",
    "University",
    "Mentoring",
    "13 Plus"
  ],
  "Foo": [
    "IB",
    "GCSE",
    "11 Plus"
  ]
}

注意:外层是一个对象而不是数组(如您的预期输出所示 - 它似乎不是有效的 JSON)。

答案2

我不知道你会如何做到这一点jq(我发现用像 perl 这样的通用语言编写一些东西比学习像jq......这样的单一用途工具更容易,如果我更频繁地使用 json 数据,它可能会是值得我花时间去学习比它最基本的用途更多的东西),但是使用 Perl 就很容易了JSON模块。

#!/usr/bin/perl
use strict;
use JSON;

# hash-of-arrays to hold an array of "level"s for each "subject"
my %merged;

# slurp the input into scalar string variable $text
my $text; { local $/; $text=<> }

my $json = JSON->new->allow_nonref;
my $data = $json->decode($text);  # parse json text into $data arrayref

# loop over each row of $data and insert into %merged
foreach my $row (@$data) {
  my $key = $row->{subject};
  my $val = $row->{level};

  push @{ $merged{$key} }, $val;
};

# pretty-print %merged as json
print $json->pretty->encode(\%merged), "\n";

示例输出:

$ ./merge-json.pl input.json 
{
   "Accounting" : [
      "A Level",
      "IB",
      "University",
      "GCSE",
      "Mentoring",
      "13 Plus",
      "11 Plus"
   ],
   "Foo" : [
      "Foo Intro",
      "Foo Basics",
      "Intermediate Foo"
   ]
}

如果您运行的是 Debian 或 Ubuntu 或类似版本,您可以使用以下命令安装 JSON 模块sudo apt-get install libjson-perl libjson-xs-perl(这应该安装 perl 本机版本模块的编译速度更快的 C 版本,JSON::XS)。它可能也适用于其他发行版。否则,请使用 进行安装cpan

答案3

与以下方法不同的方法钢铁司机的是按键对数据进行分组subject,然后将所有level值收集为各自的数组下subject

以下使用与steeldriver相同的测试数据:

$ jq 'group_by(.subject) | map({ (first.subject):  map(.level) }) | add' file
{
  "Accounting": [
    "A Level",
    "University",
    "Mentoring",
    "13 Plus"
  ],
  "Foo": [
    "IB",
    "GCSE",
    "11 Plus"
  ]
}

最后add合并前面创建的数组的元素map()

相关内容