Исключить объект, если вложенный массив содержит n вхождений строки с jq - PullRequest
1 голос
/ 07 апреля 2020

У меня есть это

[
  {
    "title": "foo",
    "label": [
      "bar-one",
      "bare-two"
    ]
  },
  {
    "title": "foo_42",
    "label": [
      "bar-one",
      "bare-two"
    ]
  },
  {
    "title": "foo_42",
    "label": [
      "bar-one"
    ]
  }
]

Я хочу подсчитать вхождения "bar" в метке массива, а затем исключить объект, если count> 1 (может быть в 2part)

ex после процесса :

[
  {
    "title": "foo_42",
    "label": [
      "bar-one"
    ]
  }
]

Я пробую разные решения, основанные на

Как выбрать элементы в JQ на основе значения в массиве

и

https://github.com/stedolan/jq/issues/861

но я не могу этого достичь!

Ответы [ 2 ]

1 голос
/ 07 апреля 2020

Кажется, это работает:

Сохраняет только элементы со свойством label, установленным в массив, содержащий только одно вхождение подстроки "bar".

map(select(.label | map(select(contains("bar"))) | length <= 1))
1 голос
/ 07 апреля 2020

Вы можете использовать функцию сокращения, принимая весь JSON в качестве входных данных, итерируя по одному объекту за раз и добавляя его к конечному результату, только если есть одно вхождение

jq -n '
    reduce inputs[] as $d (. ;
        if [ $d.label[] | select(contains("bar")) ] | length == 1 then
            . + [$d]
        else
            empty
        end
     )' \
json

Часть $d.label[] | select(contains("bar"))] |length возвращает счетчик в массиве label, сколько встречается bar. Мы добавляем его к окончательному результату . + [$d] только в том случае, если вхождение 1 или меньше 2, которое вы можете изменить при необходимости.

Или удаленный теперь ответ от oguz-ismail , который одинаково аккуратен и эффективен. Добавлено сюда как ссылка для будущих читателей

jq ' 
   map(
     select(.label |
       any(., map(select(index("bar"))); length < 2)
     )
)' json
...