json 如何使用jq按元素属性值过滤对象数组?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/38121740/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How to filter array of objects by element property values using jq?
提问by k0pernikus
I like to filter json files using jq:
我喜欢使用jq过滤 json 文件:
jq . some.json
Given the json containing an array of objects:
鉴于包含对象数组的 json:
{
"theList": [
{
"id": 1,
"name": "Horst"
},
{
"id": 2,
"name": "Fritz"
},
{
"id": 3,
"name": "Walter"
},
{
"id": 4,
"name": "Gerhart"
},
{
"id": 5,
"name": "Harmut"
}
]
}
I want to filter that list to only show the elements with id having the value 2 and 4, so the expected output is:
我想过滤该列表以仅显示 id 值为 2 和 4 的元素,因此预期输出为:
{
"id": 2,
"name": "Fritz"
},
{
"id": 4,
"name": "Gerhart"
}
How do I filter the json using jq? I have played around with select and map, yet didn't got any of those to work, e.g.:
如何使用 jq 过滤 json?我玩过选择和地图,但没有任何工作,例如:
$ jq '.theList[] | select(.id == 2) or select(.id == 4)' array.json
true
回答by André Senra
From the docs:
从文档:
jq '.[] | select(.id == "second")'Input
[{"id": "first", "val": 1}, {"id": "second", "val": 2}]Output
{"id": "second", "val": 2}
jq '.[] | select(.id == "second")'输入
[{"id": "first", "val": 1}, {"id": "second", "val": 2}]输出
{"id": "second", "val": 2}
I think you can do something like this:
我认为你可以做这样的事情:
jq '.theList[] | select(.id == 2 or .id == 4)' array.json
回答by Jeff Mercado
You could use selectwithin map.
您可以select在map.
.theList | map(select(.id == (2, 4)))
Or more compact:
或更紧凑:
[ .theList[] | select(.id == (2, 4)) ]
Though written that way is a little inefficient since the expression is duplicated for every value being compared. It'll be more efficient and possibly more readable written this way:
虽然这样写有点低效,因为表达式对于每个被比较的值都是重复的。这样写会更有效率,也可能更易读:
[ .theList[] | select(any(2, 4; . == .id)) ]
回答by peak
Using select(.id == (2, 4))here is generally inefficient (see below).
select(.id == (2, 4))在这里使用通常效率低下(见下文)。
If your jq has IN/1, then it can be used to achieve a more efficient solution:
如果您的 jq 具有IN/1,则可以使用它来实现更有效的解决方案:
.theList[] | select( .id | IN(2,3))
If your jq does not have IN/1, then you can define it as follows:
如果您的 jq 没有IN/1,那么您可以按如下方式定义它:
def IN(s): first(select(s == .)) // false;
Efficiency
效率
One way to see the inefficiency is to use debug. The following expression, for example, results in 10 calls to debug, whereas only 9 checks for equality are actually needed:
查看效率低下的一种方法是使用debug. 例如,以下表达式导致 10 次调用debug,而实际上只需要 9 次相等性检查:
.theList[] | select( (.id == (2,3)) | debug )
["DEBUG:",false]
["DEBUG:",false]
["DEBUG:",true]
{
"id": 2,
"name": "Fritz"
}
["DEBUG:",false]
["DEBUG:",false]
["DEBUG:",true]
{
"id": 3,
"name": "Walter"
}
["DEBUG:",false]
["DEBUG:",false]
["DEBUG:",false]
["DEBUG:",false]
index/1
指数/1
In principle, using index/1should be efficient, but as of this writing (October 2017), its implementation, though fast (it is written in C), is inefficient.
原则上,使用index/1应该是高效的,但在撰写本文时(2017 年 10 月),其实现虽然很快(用 C 编写),但效率低下。

