Reputation: 993
Here's my JSON:
{
"A":[
{
"AT":"text"
},
{
"AT":"text2"
}
],
"B":[
{
"name":"text",
"power":10
},
{
"name":"text1",
"power":20
},
{
"name":"text2",
"power":40
}
]
}
I want to have all B element with the same name as A element. So in this case the result would be ['text',10,'text2',40]
. I try this query [.B[] | [.name , .power][]] | map(in([.A[].AT]))
but it doesn't work it's throw me an error:
jq: error (at :23): Cannot index string with string "A" exit status 5
I don't know how to fix it but I think it's about the parent node, it doesn't recognize the nested query in the in function. So is it possible to make nested query in this language and how can handle a problem with nested query for other case like other function or other situation as pipe ?
PS: I work in JAVASCRIPT (node.js)
New problem, I have this query:
( .Move | map({(.name): {accuracy : .url.accuracy, damage_class: .url.damage_class.name, power : .url.power, priority: .url.priority, target: .url.target.name, type: .url.type.name, null}}) | add ) as $b | .results | select(.name=="bulba") | map(.url.moves[].move.name | [., $b[.][]]) | add
and it's work perfectly without select(.name=="bulba")
jq: error (at :158): Cannot index array with string "name"
Should I show the JSON with this ?(because is a little bigger than the previous one) But it's start with this:
{
"results":[
{
"name":"bulba",
"url":{
"moves":[
{
"move":{
"name":"flamiche"
}
}
]
}
},
{
"name":"sala",
"url":{
"moves":[
{
"move":{
"name":"DAMSSSS"
}
}
]
}
}
],
"Move":[
{
"name":"flamiche",
"url":{
"accuracy":50,
"damage_class":{
"name":"physical"
},
"power":50,
"priority":0,
"target":{
"name":"foe"
},
"type":{
"name":"fire"
}
}
},
{
"name":"DAMSSSS",
"url":{
"accuracy":90,
"damage_class":{
"name":"status"
},
"power":null,
"priority":2,
"target":{
"name":"self"
},
"type":{
"name":"grass"
}
}
}
]
}
Upvotes: 3
Views: 2498
Reputation: 50750
You're piping [.B[] | [.name , .power][]]
's product --which is to be an array of strings-- to map(in([.A[].AT]))
, i.e input is changed and .A
is lost, and you're trying to get .A[].AT
from those strings. This is not the only issue but the reason why you get that error. You better do something like this:
( .B | map({(.name): .power}) | add ) as $b
| .A | map(.AT | [., $b[.]]) | add
If your input is too big using reduce
you can get better performance:
( reduce .B[] as $b ({}; . + ($b | {(.name): .power})) ) as $b
| reduce .A[].AT as $a ([]; . + [$a, $b[$a]])
As for your second question, by passing results
, an array of objects, to select(.name=="bulba")
, as the error message states you're trying to index an array with a string. To filter objects under results
move select
into map
like:
map(select(.name == "bulba") | .url.moves[].move.name | [., $b[.][]])
Upvotes: 2
Reputation: 26844
If you want to get all B
objects that are on A
, you can use Set
and concat
to create an object with all the A values. Use filter
to filter the object B
var obj = {"A":[{"AT":"text"},{"AT":"text2"}],"B":[{"name":"text","power":10},{"name":"text1","power":20},{"name":"text2","power":40}]}
var allAs = new Set([].concat(...obj.A.map(o => Object.values(o))));
var result = obj.B.filter(o => allAs.has(o.name));
console.log(result);
You can also use flatMap
(available on Node 11.0.0) as:
var obj = {"A":[{"AT":"text"},{"AT":"text2"}],"B":[{"name":"text","power":10},{"name":"text1","power":20},{"name":"text2","power":40}]}
var allAs = new Set(obj.A.flatMap(o => Object.values(o)));
var result = obj.B.filter(o => allAs.has(o.name));
console.log(result);
Upvotes: 0