如何使用jq按元素属性值过滤对象数组?

k0p*_*kus 27 json jq

我喜欢使用jq过滤json文件:

jq . some.json
Run Code Online (Sandbox Code Playgroud)

给定json包含一个对象数组:

{
  "theList": [
    {
      "id": 1,
      "name": "Horst"
    },
    {
      "id": 2,
      "name": "Fritz"
    },
    {
      "id": 3,
      "name": "Walter"
    },
    {
      "id": 4,
      "name": "Gerhart"
    },
    {
      "id": 5,
      "name": "Harmut"
    }
  ]
}
Run Code Online (Sandbox Code Playgroud)

我想过滤该列表只显示id为2和4的元素,因此预期输出为:

{
  "id": 2,
  "name": "Fritz"
},
{
  "id": 4,
  "name": "Gerhart"
}
Run Code Online (Sandbox Code Playgroud)

如何使用jq过滤json?我玩过选择和地图,但没有任何工作,例如:

$ jq '.theList[] | select(.id == 2) or select(.id == 4)' array.json
true
Run Code Online (Sandbox Code Playgroud)

And*_*nra 38

来自文档:

jq '.[] | select(.id == "second")' 
Run Code Online (Sandbox Code Playgroud)

输入 [{"id": "first", "val": 1}, {"id": "second", "val": 2}]

产量 {"id": "second", "val": 2}

我想你可以这样做:

jq '.theList[] | select(.id == 2 or .id == 4)' array.json
Run Code Online (Sandbox Code Playgroud)

  • 它返回两个子句的评估,试试这个:`jq'.theList [] | 选择(.id == 2或.id == 4)'` (2认同)

Jef*_*ado 9

你可以select在里面使用map.

.theList | map(select(.id == (2, 4)))
Run Code Online (Sandbox Code Playgroud)

或者更紧凑:

[ .theList[] | select(.id == (2, 4)) ]
Run Code Online (Sandbox Code Playgroud)

虽然以这种方式编写的方式效率有点低,因为对于每个被比较的值,表达式都是重复的.以这种方式编写它会更有效,也可能更具可读性:

[ .theList[] | select(any(2, 4; . == .id)) ]
Run Code Online (Sandbox Code Playgroud)


pea*_*eak 5

select(.id == (2, 4))在这里使用通常效率低下(见下文)。

如果您的 jq 具有IN/1,则可以使用它来实现更有效的解决方案:

.theList[] | select( .id | IN(2,3))
Run Code Online (Sandbox Code Playgroud)

如果您的 jq 没有IN/1,那么您可以按如下方式定义它:

def IN(s): first(select(s == .)) // false;
Run Code Online (Sandbox Code Playgroud)

效率

查看效率低下的一种方法是使用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]
Run Code Online (Sandbox Code Playgroud)

指数/1

原则上,使用index/1应该是高效的,但在撰写本文时(2017 年 10 月),其实现虽然很快(用 C 编写),但效率低下。