repetidos query objetos elementos elemento buscar array json jq

json - query - map javascript



¿Cómo filtrar una matriz de objetos por valores de propiedades de elementos usando jq? (4)

Me gusta filtrar archivos json usando jq :

jq . some.json

Dado el json que contiene una matriz de objetos:

{ "theList": [ { "id": 1, "name": "Horst" }, { "id": 2, "name": "Fritz" }, { "id": 3, "name": "Walter" }, { "id": 4, "name": "Gerhart" }, { "id": 5, "name": "Harmut" } ] }

Quiero filtrar esa lista para mostrar solo los elementos con id que tienen el valor 2 y 4, por lo que la salida esperada es:

{ "id": 2, "name": "Fritz" }, { "id": 4, "name": "Gerhart" }

¿Cómo puedo filtrar el json usando jq? He jugado con selección y mapa, pero no conseguí que ninguno de ellos funcionara, por ejemplo:

$ jq ''.theList[] | select(.id == 2) or select(.id == 4)'' array.json true


Aquí hay una solución utilizando indices :

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


El uso de la select(.id == (2, 4)) aquí es generalmente ineficiente (ver más abajo).

Si su jq tiene IN/1 , entonces puede usarse para lograr una solución más eficiente:

.theList[] | select( .id | IN(2,3))

Si su jq no tiene IN/1 , entonces puede definirlo de la siguiente manera:

def IN(s): first(select(s == .)) // false;

Eficiencia

Una forma de ver la ineficiencia es utilizar la debug . La siguiente expresión, por ejemplo, da como resultado 10 llamadas a debug , mientras que solo se necesitan 9 comprobaciones de igualdad:

.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]

índice / 1

En principio, el uso de index/1 debe ser eficiente, pero a partir de este escrito (octubre de 2017), su implementación, aunque rápida (está escrito en C), es ineficiente.


Podrías usar select dentro del map .

.theList | map(select(.id == (2, 4)))

O más compacto:

[ .theList[] | select(.id == (2, 4)) ]

Aunque escrito de esta manera es un poco ineficiente ya que la expresión se duplica para cada valor que se compara. Será más eficiente y posiblemente más legible escrito de esta manera:

[ .theList[] | select(any(2, 4; . == .id)) ]


De los documentos:

jq ''.[] | select(.id == "second")''

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

Salida {"id": "second", "val": 2}

Creo que puedes hacer algo como esto:

jq ''.theList[] | select(.id == 2 or .id == 4)'' array.json