Выбрать элементы в массиве на основе значения свойства - PullRequest
2 голосов
/ 25 мая 2020

Как разработчик, когда я использую следующую команду JQ:

.first_level. "Second_level" [] | = select (.fruit == "pear")

И я применяю его к этому JSON:

{
  "first_level": {
    "second_level": [
      {
        "fruit": "apple"
      },
      {
        "fruit": "pear"
      },
      {
        "fruit": "banana"
      },
      {
        "fruit": "donuts"
      }
    ]
  }

}

Затем я хотел бы получить этот результат (только сохраняйте элементы со свойством fruit равным pear):

{
  "first_level": {
    "second_level": [
      {
        "fruit": "pear"
      }
    ]
  }

}

Но текущее возвращаемое значение (также можно увидеть в JQ Play здесь ):

{
  "first_level": {
    "second_level": [
      {
        "fruit": "pear"
      },
      {
        "fruit": "donuts"
      }
    ]
  }
}

-> Оно сохраняет значение с donuts и чего я не понимаю, так это того, что из документации JQ |= должен назначать значение выбора, но при запуске:

.first_level. "Second_level" [] | select (.fruit == "pear")

У меня следующий результат:

{
  "fruit": "pear"
}

-> Кажется, выбор был успешным, но эффект не действует как я и ожидал (он добавляет donuts).

Любая помощь с этой проблемой будет принята с благодарностью. Заранее спасибо! :)

1 Ответ

2 голосов
/ 25 мая 2020

Учитывая ваш пример ввода, эта программа в основном делает следующее:

.first_level.second_level |= (
    delpaths([[0]]) # apple != pear
  | delpaths([[1]]) # banana != pear
  | delpaths([[2]]) # null != pear
  | delpaths([[3]]) # null != pear
)

Посмотрите, как реализована основная встроенная функция для |= здесь ; когда правая часть |= применяется к значению пути, если результат равен empty, этот путь удаляется с помощью delpaths. Итак, проблема ясна, когда .[0] (яблоко) удаляется, .[1] (груша) становится .[0]; но _modify не учитывает это изменение, поскольку он принимает список путей, которые нужно изменить один раз в начале, и не обновляется снова, а продолжает .[1] (банан).

Вы вместо этого можно использовать:

del(.first_level.second_level[] | select(.fruit != "pear"))

Или, если вы настаиваете на решении, включающем |=:

.first_level.second_level |= map(select(.fruit == "pear"))
...