Использование JQ, как найти/удалить один элемент в массиве json и удалить тот же индекс элемента в другом массиве

У меня есть массив json из сотен объектов, и каждый объект содержит (среди многих других полей) два таких массива и индикатор состояния:

"searchMetaData": {"rrStandard": ["XYZ5.1","6.3"],"ccStandard": ["46d45a68-a930","8cd1dc9a-d6a2"],"status": "complete"}

Для любого объекта со статусом «завершен» я хочу просмотреть массив rrStandard и удалить все элементы массива, которые не начинаются с XYZ (т. е. будет удалено «6.3»). Но мне также нужно удалить соответствующий элемент в массиве ccStandard, но в этом массиве нет шаблонов, по которым я мог бы сопоставить, поэтому я думаю, что мне придется удалить на основе соответствующего индексного номера.

Есть ли способ с помощью jq удалить «6.3» из rrStandard, каким-то образом запомнить, каким был его индекс (например, 1), а затем удалить элемент с тем же индексом (например, индекс 1) в массиве ccStandard?

В производственном случае эти массивы иногда будут иметь более двух значений в массивах, но количество элементов в них будет совпадать. Итак, возможно, мне нужно удалить элементы 1,2 и 3, например, в обоих массивах.

Я новичок в jq и (я думаю) понял, как найти и удалить «6.3» из rrStandard, но оттуда я заблудился.

Вот что мне удалось просто найти и удалить «6.3» из rrStandard:

.[].searchMetaData |= if (.status == "complete") then (del(.rrStandard[] | select(startswith("XYZ") | not))) else . end
Как сделать HTTP-запрос в Javascript?
Как сделать HTTP-запрос в Javascript?
В JavaScript вы можете сделать HTTP-запрос, используя объект XMLHttpRequest или более новый API fetch. Вот пример для обоих методов:
0
0
56
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Один из способов — использовать to_entries для получения массива индексов и значений, фильтрации значений и использования индексов для удаления из обоих массивов. В качестве альтернативы, как предлагает @oguz, используйте path для получения индексов:

del(.[].searchMetaData | select(.status == "complete") | (
  .rrStandard, .ccStandard
)[
  .rrStandard | to_entries[] | select(.value | startswith("XYZ") | not).key
  # or:  .rrStandard | path(.[] | select(startswith("XYZ") | not))[]
])

Демо 1Демо 2

Другой способ — переместить reduce над keys в одном массиве и удалить из обоих массивов, если есть совпадение. Итерация сделана для того, чтобы reverse не затрагивала более высокие индексы после удаления более низких:

(.[].searchMetaData | select(.status == "complete")) |= reduce (
  .rrStandard | keys | reverse[]
) as $i (.;
  del((.rrStandard, .ccStandard)[
    select(.rrStandard[$i] | startswith("XYZ") | not) | $i
  ])
)

Демо

Еще один способ — скоординировать оба массива и transpose их дважды. После первого элементы выстраиваются в ряд, и совпадающие можно удалить за один раз:

(.[].searchMetaData | select(.status == "complete")) |= . + (
  [.rrStandard, .ccStandard]
  | transpose | map(select(first | startswith("XYZ")))
  | transpose | {rrStandard: first, ccStandard: last}
)

Демо

Ответ принят как подходящий

Вы ищете что-то вроде этого:

(.[].searchMetaData | select(.status == "complete")) |=
[.rrStandard | path (.[] | select(startswith("XYZ") | not))] as $p
| (.rrStandard, .ccStandard) |= delpaths($p)

Спасибо. Кажется, это работает. Я заметил, что когда я просматриваю его в своем текстовом редакторе, он оставляет пустую строку в массиве, где удаленный элемент массива раньше находился в обоих массивах.

Rogelio 26.08.2024 16:21

@Рогелио, я не думаю, что это как-то связано с jq

oguz ismail 26.08.2024 16:47

Да, я думаю, ты прав. Я пытался расшифровать это. Похоже, что после текста и перед символом закрывающего массива "]" есть символ CR/LF, который не удаляется, и этот CR/LF не удаляется. Я являюсь посредником между поставщиком моего поставщика json и другим поставщиком, которому я отправляю json, но углублюсь в это.

Rogelio 26.08.2024 17:29

@Rogelio Удачи, хорошего дня.

oguz ismail 26.08.2024 18:17

Другие вопросы по теме