Reputation: 55
I got two .json files, the first one contains the data:
data.json
[
{"ID_EXT_LARGE":"aaa_1234411","xy":"xyz"},
{"ID_EXT_LARGE":"bbb_1474411","xy":"cfg"},
{"ID_EXT_LARGE":"ccc_8944411","xy":"drt"},
{"ID_EXT_LARGE":"aaa_1234411","xy":"kai"}
]
The other one contains the IDs:
id_array.json
[
{"ID_EXT":"aaa","ID_WEB":30,"ID_ACC":"one"},
{"ID_EXT":"bbb","ID_WEB":40,"ID_ACC":"two"},
{"ID_EXT":"ccc","ID_WEB":50,"ID_ACC":"three"}
]
Now I try to get the "ID_WEB" and "ID_ACC" propertie into the objects of data.json, using the mapping of ID_EXT_LARGE and ID_EXT.
The problem is, that ID_EXT only contains the first characters of ID_EXT_LARGE. Expected result - (should be the extended data.json file):
data.json
[
{"ID_EXT_LARGE":"aaa_1234411","ID_WEB":30,"ID_ACC":"one","xy":"xyz"},
{"ID_EXT_LARGE":"bbb_1474411","ID_WEB":40,"ID_ACC":"two","xy":"cfg"},
{"ID_EXT_LARGE":"ccc_8944411","ID_WEB":50,"ID_ACC":"three","xy":"drt"},
{"ID_EXT_LARGE":"aaa_1234411","ID_WEB":30,"ID_ACC":"one","xy":"kai"}
]
I tried it for ID_WEB and was thinking of something like this, (the for loop was just an idea):
script.jq
def getIDWEB(id_array);
for i ....
if ."ID_EXT_LARGE"|startswith(id_array[i].ID_EXT) then id_array[i].ID_WEB end
end
;
def setIDWEB(id_array):
.ID_WEB = getIDWEB(id_array)
;
($id_array) as $id_array
| map(setIDWEB($id_array))
Probably I am thinking too complicated and this is actually a one-liner?
Upvotes: 0
Views: 657
Reputation: 14715
Here is an approach which builds a "table" object from id_array.json
. This function creates the table:
def maketable:
reduce $id_array[] as $i (
{}
; .[$i.ID_EXT] = ($i | {ID_WEB,ID_ACC})
)
;
With the sample id_array.json
in $id_array
this returns an object like
{
"aaa": {
"ID_WEB": 30,
"ID_ACC": "one"
},
"bbb": {
"ID_WEB": 40,
"ID_ACC": "two"
},
"ccc": {
"ID_WEB": 50,
"ID_ACC": "three"
}
}
This function takes an object from data.json
and returns the corresponding lookup key for the table:
def getkey: .ID_EXT_LARGE | split("_")[0] ;
e.g. given
{"ID_EXT_LARGE":"aaa_1234411","xy":"xyz"}
it returns
"aaa"
With these two functions the result output can be generated with:
maketable as $idtable
| map( . + $idtable[ getkey ] )
Here is a script which puts everything together and uses sponge
to update data.json
:
#!/bin/bash
jq -M --argfile id_array id_array.json '
def maketable:
reduce $id_array[] as $i (
{}
; .[$i.ID_EXT] = ($i | {ID_WEB,ID_ACC})
)
;
def getkey: .ID_EXT_LARGE | split("_")[0] ;
maketable as $idtable
| map( . + $idtable[ getkey ] )
' data.json | sponge data.json
Here is data.json
after a sample run:
[
{
"ID_EXT_LARGE": "aaa_1234411",
"xy": "xyz",
"ID_WEB": 30,
"ID_ACC": "one"
},
{
"ID_EXT_LARGE": "bbb_1474411",
"xy": "cfg",
"ID_WEB": 40,
"ID_ACC": "two"
},
{
"ID_EXT_LARGE": "ccc_8944411",
"xy": "drt",
"ID_WEB": 50,
"ID_ACC": "three"
},
{
"ID_EXT_LARGE": "aaa_1234411",
"xy": "kai",
"ID_WEB": 30,
"ID_ACC": "one"
}
]
Note that as peak points out maketable
could be replaced with
def maketable: INDEX($id_array[]; .ID_EXT) | map_values(del(.ID_EXT)) ;
if the more general INDEX builtin (definition below) is available.
def INDEX(stream; idx_expr):
reduce stream as $row (
{}
; .[$row|idx_expr| if type != "string" then tojson else . end] |= $row
)
;
Upvotes: 1