如何使用jq将对象键转换为数组

问题描述

我正在尝试转换csv,其中标头是键,列中的值是列表。

例如,我有以下csv

               mpg   cyl  disp  hp   drat  wt     qsec   vs  am  gear  carb
Mazda RX4      21    6    160   110  3.9   2.62   16.46  0   1   4     4
Mazda RX4 Wag  21    6    160   110  3.9   2.875  17.02  0   1   4     4
Datsun 710     22.8  4    108   93   3.85  2.32   18.61  1   1   4     1

我想要以下格式。

{
    "field1" : [Mazda RX4,Mazda RX4 Wag,Datsun 710],"mpg" : [21,21,22.8],"cyl" : [6,6,6],"disp" : [160,160,108],...
}

请注意,未引用数值。我假设所有列都具有相同的类型。

我正在使用以下jq命令。

 curl https://raw.githubusercontent.com/vincentarelbundock/Rdatasets/master/csv/datasets/mtcars.csv  cars.csv | head -n4 | csvtojson | jq '.'
[
  {
    "field1": "Mazda RX4","mpg": "21","cyl": "6","disp": "160","hp": "110","drat": "3.9","wt": "2.62","qsec": "16.46","vs": "0","am": "1","gear": "4","carb": "4"
  },{
    "field1": "Mazda RX4 Wag","wt": "2.875","qsec": "17.02",{
    "field1": "Datsun 710","mpg": "22.8","cyl": "4","disp": "108","hp": "93","drat": "3.85","wt": "2.32","qsec": "18.61","vs": "1","carb": "1"
  }
]

解决方法

这是一个基于mapreduce的简洁,高效且概念上简单的解决方案:

. as $in
| reduce (.[0] | keys_unsorted[]) as $k ( {}; .[$k] = ($in|map(.[$k])))

将所有数值字符串转换为数字

. as $in
| reduce (.[0] | keys_unsorted[]) as $k ( {}; 
    .[$k] = ($in|map(.[$k] | (tonumber? // .))))