1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

jqで二次元配列の行と列を入れ替える。

Posted at

jqで↓これを

[
    {
        "role": "A",
        "members": ["taro", "hanako"]
    },
    {
        "role": "B",
        "members": ["jiro"]
    },
    {
        "role": "C",
        "members": ["hanako", "jiro"]
    }
]

↓こうしたい

[
    {
        "member": "taro",
        "role": ["A"]
    },
    {
        "member": "jiro",
        "role": ["B", "C"]
    },
    {
        "member": "hanako",
        "role": ["A","C"]
    },
]

二次元配列の転置ですかね。
行列の入れ替え。

やりかた

jq 'map({"role": .role, "member": .members[]}) | group_by(.member) | map({"member": .[0].member, "role": map(.role)})'

解説

参考

いきなり理解するのは苦しいので、ひとつずつ解説。

元データ

再掲

[
    {
        "role": "A",
        "members": ["taro", "hanako"]
    },
    {
        "role": "B",
        "members": ["jiro"]
    },
    {
        "role": "C",
        "members": ["hanako", "jiro"]
    }
]

map({"role": .role, "member": .members[]})

まずは、配列を展開して下記の形に変換します。

[
  {
    "role": "A",
    "member": "taro"
  },
  {
    "role": "A",
    "member": "hanako"
  },
  {
    "role": "B",
    "member": "jiro"
  },
  {
    "role": "C",
    "member": "hanako"
  },
  {
    "role": "C",
    "member": "jiro"
  }
]

こちらの記事にもお世話になりました。
書き方違いますが、参考にどうぞ。

group_by(.member)

members毎に集め直します。

[
  [
    {
      "role": "A",
      "member": "hanako"
    },
    {
      "role": "C",
      "member": "hanako"
    }
  ],
  [
    {
      "role": "B",
      "member": "jiro"
    },
    {
      "role": "C",
      "member": "jiro"
    }
  ],
  [
    {
      "role": "A",
      "member": "taro"
    }
  ]
]

map({"member": .[0].member, "role": map(.role)})

最後がややこしいですね。

↓これを

  [
    {
      "role": "A",
      "member": "hanako"
    },
    {
      "role": "C",
      "member": "hanako"
    }
  ]

↓これに変換する事を考えてみます。

  {
    "member": "hanako",
    "role": [
      "A",
      "C"
    ]
  }

入力された各要素を使って目的のオブジェクトを組み立てます。

"member": .[0].member

一つ前の手順で group_by() しているので、.member は全部同じはずです。
なので、1つ目の member の値を採用します。

"role": map(.role)

map関数を使って、各要素を集めて配列にまとめます。

map({ })

集めた各要素をオブジェクトとして出力します。
map関数なので、配列で出力されます。

参考

完成

全部まとめると、行列が入れ替わりました。

[
  {
    "member": "hanako",
    "role": [
      "A",
      "C"
    ]
  },
  {
    "member": "jiro",
    "role": [
      "B",
      "C"
    ]
  },
  {
    "member": "taro",
    "role": [
      "A"
    ]
  }
]

備考

記事を書くために jqplay.org 使ってみました。
便利ですね。

1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?