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

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-03 18:29:08  来源:igfitidea点击:

How to filter array of objects by element property values using jq?

jsonjq

提问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.

您可以selectmap.

.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 编写),但效率低下。

回答by jq170727

Here is a solution using indices:

这是使用索引的解决方案:

.theList | [ .[map(.id)|indices(2,4)[]] ]