Как отфильтровать элементы с определенным свойством (или оставить элементы без этого свойства) - PullRequest
1 голос
/ 05 августа 2020

Я обрабатываю вывод из dcm2 json, который преобразует метаданные из данных медицинских изображений в формате DICOM в JSON. Значения для этих метаданных в основном представляют собой строки, целые числа, числа с плавающей запятой и т.п., но они также включают встроенные двоичные значения в виде строк в кодировке base64. Нам не нужны эти двоичные файлы, и они могут стать довольно большими, поэтому мне нужно отфильтровать все элементы метаданных, у которых есть свойство InlineBinary. Ниже приведен (очень простой небольшой) образец вывода JSON из dcm2 json:

{
    "00080005": {
        "vr": "CS",
        "Value": ["ISO_IR 192"]
    },
    "00291010": {
        "vr": "OB",
        "InlineBinary": "Zm9vYmFyCg=="
    }
}

Я хочу преобразовать это в:

{
    "00080005": {
        "vr": "CS",
        "Value": ["ISO_IR 192"]
    }
}

Я пробовал несколько разные вещи, которые не работали, но в конечном итоге использовали это:

$ dcm2json file.dcm | jq '[to_entries | .[] | select(.value.Value)] | from_entries'

Я продолжал играть с ним, потому что мне не нравится, когда это выражение встроено в массив (например, [to_entries ...]). Я придумал что-то более элегантное, но совершенно не понимаю, почему это работает именно так:

jq 'to_entries | . - map(select(.value | has("InlineBinary") == true)) | from_entries' | less

Что сбивает с толку, так это бит has("InlineBinary") == true. Сначала я сравнил его с false, потому что мне нужны были те элементы, которые не имеют свойство InlineBinary. Почему это работает как бы противоположно тому, о чем я думаю? Учитывая, что я действительно не понимаю, что происходит там со структурой . - map(...) (я полностью удалил ее из другого сообщения, где кто-то задавал аналогичный вопрос), я не удивлен, что он делает что-то, чего я не понимаю, но я ' Я хочу понять, почему это так:)

Еще одна вещь, которая меня смущает, - это to_entries/from_entries/with_entries. В руководстве по говорится об этих :

with_entries (foo) - это сокращение от to_entries | карта (foo) | from_entries

Круто! Так что это будет:

jq 'with_entries(map( . - map(select(.value | has("InlineBinary") == true))))'

Но это не работает:

$ cat 1.json | jq 'with_entries(map(. - map(select(.value | has("InlineBinary") == true))))'
jq: error (at <stdin>:848): Cannot iterate over string ("00080005")

Учитывая, что этот оператор должен быть функционально эквивалентным, я не уверен, почему это не t работает.

Спасибо за любую информацию, которую вы можете предоставить!

1 Ответ

1 голос
/ 05 августа 2020

При выборе пар ключ-значение часто выбирают with_entries:

with_entries( select(.value | has("InlineBinary") | not) )
...