Reputation: 49
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.
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.
Upvotes: 1
Views: 358
Reputation: 92854
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
}
]
Upvotes: 0
Reputation: 116740
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) )
Upvotes: 3