I want to count the number of "domains" for which "adminLock" is equal to 1.
This is my json data structure:
{
"code": 0,
"message": "成功",
"data": {
"recordCount": "128",
"pageSize": 100,
"page": 1,
"pageCount": 2,
"data": [
{
"domainsID": "173652434",
"nsGroupID": "199",
"groupID": "78987",
"domains": "dome1.com",
"state": 3,
"userLock": 0,
"adminLock": 0,
"view_type": "1"
},
{
"domainsID": "173205836",
"nsGroupID": "199",
"groupID": "78987",
"domains": "dome2.com",
"state": 3,
"userLock": 0,
"adminLock": 1,
"view_type": "1"
},
{
"domainsID": "173205812",
"nsGroupID": "199",
"groupID": "78987",
"domains": "dome3.com",
"state": 3,
"userLock": 0,
"adminLock": 0,
"view_type": "1"
},
{
"domainsID": "173203610",
"nsGroupID": "199",
"groupID": "78987",
"domains": "dome4.com",
"state": 3,
"userLock": 0,
"adminLock": 1,
"view_type": "1"
},
{
"domainsID": "173203210",
"nsGroupID": "199",
"groupID": "78987",
"domains": "dome5.com",
"state": 3,
"userLock": 0,
"adminLock": 1,
"view_type": "1"
},
{
"domainsID": "173203131",
"nsGroupID": "199",
"groupID": "78987",
"domains": "dome6.com",
"state": 3,
"userLock": 0,
"adminLock": 1,
"view_type": "1"
},
{
"domainsID": "173203074",
"nsGroupID": "199",
"groupID": "78987",
"domains": "dome7.com",
"state": 3,
"userLock": 0,
"adminLock": 1,
"view_type": "1"
}
],
"nextPage": 2
}
}
Here's what I have so far:
'.data.data[] | select(.adminLock == 1) | .domains'
I can get the value of .domains, but how can I count how many times it occurs?
Replenish
The script I am using is the bash shell This command gets the value, I want to count the domains value in the case of adminLock=1, and count the number of domains ———————— Judging that adminLock=1 is getting the domains value, and counting how many in total
CodePudding user response:
To have a single count of all resulting items, either make an array and determine its length
:
.data.data | map(select(.adminLock == 1)) | length
5
Or iterate and count, e.g. using reduce
:
reduce (.data.data[] | select(.adminLock == 1)) as $i (0; . 1)
5
The first approach may seem more "natural" but it actually builds up an array that you eventually may not need. Therefore, if you only need the count, not the items themselves, use the second approach.
To count the items based on a certain property, say, the distinct values of .domains
, create an according structure and count as shown before. The array approach could group the items using group_by
:
.data.data | map(select(.adminLock == 1)) | group_by(.domains)
| map("\(first.domains): \(length)") # create your desired format
[
"dome2.com: 1",
"dome4.com: 1",
"dome5.com: 1",
"dome6.com: 1",
"dome7.com: 1"
]
The iterative approach successively builds up your output structure, e.g. an object with the property as field names:
reduce (.data.data[] | select(.adminLock == 1)) as $i (
{}; .[$i.domains] = 1 # create your desired format
)
{
"dome2.com": 1,
"dome4.com": 1,
"dome5.com": 1,
"dome6.com": 1,
"dome7.com": 1
}
CodePudding user response:
In general, rather than constructing an array, it's better to use a stream-oriented counting method:
def count(s): reduce s as $x (0;. 1);
In your case, it seems you could get away with:
count(.data.data[] | select(.adminLock == 1))
but perhaps you would want to check there is a domains
key:
count(.data.data[] | select(.adminLock == 1 and has("domains") ))
If, however, you want to count the number of distinct domains satisfying the condition, it would probably be simplest to use unique
:
[.data.data[] | select(.adminLock == 1) | .domains] | unique | length
But it's not hard to write a stream-oriented version of unique
to avoid having to call unique/0
...