简体   繁体   中英

jq 1.5: Combining keys from one array with their values that are in a different array

I'd like to take some key values that are found in one array, and match them with their corresponding values in a different array. For reference I'm using jq-1.5

I've got some data from the quandl api where I'm pulling some stock data. For example, the following pulls down some json data.

curl https://www.quandl.com/api/v3/datatables/WIKI/PRICES.json?ticker=FB&qopts.columns=date,close,high,low&api_key=myapikeyblahblah

The data is as follows, though I've removed some of the redundant data;

{
  "datatable": {
    "data": [
      ["2012-05-18", 38.2318, 45.0, 38.0],
      ["2012-05-21", 34.03, 36.66, 33.0],
      ["2012-05-22", 31.0, 33.59, 30.94],
      ["2017-06-22", 153.4, 154.55, 152.91],
      ["2017-06-23", 155.07, 155.2, 152.65]
    ],
    "columns": [{
      "name": "date",
      "type": "Date"
    }, {
      "name": "close",
      "type": "BigDecimal(34,12)"
    }, {
      "name": "high",
      "type": "BigDecimal(34,12)"
    }, {
      "name": "low",
      "type": "BigDecimal(34,12)"
    }]
  },
  "meta": {
    "next_cursor_id": null
  }
}

I'm looking to match the "keys" from the .datatable.columns[$index1].name with the "values" in .datatable.data[1] and so on with each iterating index value. I'm looking to get an output like the following;

[
  {
    "date": "2012-05-18",
    "close": 38.2318,
    "high": 45.0,
    "low": 38.0
  },
  {
    "date": "2012-05-21",
    "close": 34.03,
    "high": 36.66,
    "low": 33.0
  },
  {
    "date": "2012-05-22",
    "close": 31.0,
    "high": 33.59,
    "low": 30.94
  },
  {
    "date": "2017-06-22",
    "close": 153.4,
    "high": 154.55,
    "low": 152.91
  },
  {
    "date": "2017-06-23",
    "close": 155.07,
    "high": 155.2,
    "low": 152.65
  }
]

So far i've played around with the idea of counting up the index, but most of my solutions so far have been fairly verbose, and i'm finding myself stepping out of jq to sed/awk etc for something that I imagine is easy in jq.

Here's a helper function to make the solution easy to understand. It converts the input array into an object, on the assumption that headers is an array of strings to be used as key names:

def objectify(headers):
  [headers, .] | transpose | map( { (.[0]): .[1] } ) | add;

A solution is now straightforward:

.datatable
| (.columns | map(.name)) as $headers
| .data
| map( objectify($headers) )

Python solution:

combine_keys.py script:

import sys, json

data = json.load(open(sys.argv[1], 'r'))
columns = [o['name'] for o in data['datatable']['columns']]
result = json.dumps([dict(zip(columns, i)) for i in data['datatable']['data']], indent=4)
print(result)

Usage :

python combine_keys.py input.json

The output:

[
    {
        "low": 38.0,
        "date": "2012-05-18",
        "close": 38.2318,
        "high": 45.0
    },
    {
        "low": 33.0,
        "date": "2012-05-21",
        "close": 34.03,
        "high": 36.66
    },
    {
        "low": 30.94,
        "date": "2012-05-22",
        "close": 31.0,
        "high": 33.59
    },
    {
        "low": 152.91,
        "date": "2017-06-22",
        "close": 153.4,
        "high": 154.55
    },
    {
        "low": 152.65,
        "date": "2017-06-23",
        "close": 155.07,
        "high": 155.2
    }
]

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM