配列からのキーの入力json文字列を指定すると、元のオブジェクトと入力配列にキーが含まれるエントリのみを含むオブジェクトを返します。
私には解決策がありますが、それはエレガントではなく({($k):$input[$k]}
は特に不格好に感じます...)、これは私が学ぶチャンスだと思います。
jq -n '{"1":"a","2":"b","3":"c"}' \
| jq --arg keys '["1","3","4"]' \
'. as $input
| ( $keys | fromjson )
| map( . as $k
| $input
| select(has($k))
| {($k):$input[$k]}
)
| add'
これをクリーンアップする方法はありますか?
jqを使用してネストされたJSONオブジェクトから選択したプロパティを抽出する は良い出発点であるように感じますが、それを機能させることはできません。
内部チェックによる解決策:
jq 'with_entries(select([.key] | inside(["key1", "key2"])))'
このフィルターを使用できます:
with_entries(
select(
.key as $k | any($keys | fromjson[]; . == $k)
)
)
内部演算子はほとんどの時間機能します。ただし、内部演算子に副作用があることがわかりました。入力が{ "key1": val1, "key2": val2, "key12": val12 }
であり、inside(["key12"])
で選択すると、"key1"
と"key12"
の両方が選択される場合があります。
完全一致が必要な場合は、in演算子を使用します。このようにすると、.key2
と.key12
のみが選択されます
jq 'with_entries(select(.key | in({"key2":1, "key12":1})))'
in演算子はオブジェクトからのキーのみ(または配列からのインデックスexists?
)をチェックするため、ここでは目的のキーをキーとしてオブジェクト構文で記述する必要がありますが、値は重要ではありません。 in演算子の使用は、この目的には完全ではありません。JavascriptES6に、jqビルトインとして実装されるAPIの逆バージョンが含まれていることを確認したいと思います
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/includes
jq 'with_entries(select(.key | included(["key2", "key12"])))'
アイテムをチェックするには.key
は配列からincluded?
です
ジェフの答えには、いくつかの不必要な非効率性があります。どちらも、--argjson keys
の代わりに--arg keys
が使用されていると仮定して、次のように対処します。
with_entries( select( .key as $k | $keys | index($k) ) )
ここにいくつかの追加の説明があります
入力オブジェクトの場合{"key1":1, "key2":2, "key3":3}
目的のキーのセットに含まれていないすべてのキーを削除したい["key1","key3","key4"]
jq -n --argjson desired_keys '["key1","key3","key4"]' \
--argjson input '{"key1":1, "key2":2, "key3":3}' \
' $input
| with_entries(
select(
.key == ($desired_keys[])
)
)'
with_entries
は、{"key1":1, "key2":2, "key3":3}
を次のキーと値のペアの配列に変換し、selectステートメントを配列にマップしてから、結果の配列をオブジェクトに戻します。
これがwith_entries
ステートメントの内部オブジェクトです。
[
{
"key": "key1",
"value": 1
},
{
"key": "key2",
"value": 2
},
{
"key": "key3",
"value": 3
}
]
次に、この配列から基準を満たすキーを選択できます。
ここで魔法が起こります...このコマンドの途中で何が起こっているかを見てみましょう。次のコマンドは、展開された値の配列を取得し、それらを選択可能なオブジェクトのリストに変換します。
jq -cn '{"key":"key1","value":1}, {"key":"key2","value":2}, {"key":"key3","value":3}
| select(.key == ("key1", "key3", "key4"))'
これにより、次の結果が得られます
{"key":"key1","value":1}
{"key":"key3","value":3}
With entryコマンドは少し注意が必要ですが、フィルターを使用し、次のように定義されていることを覚えておくのは簡単です。
def with_entries(f): to_entries|map(f)|from_entries;
これはと同じです
def with_entries(f): [to_entries[] | f] | from_entries;
人々を混乱させる質問の他の部分は、==
の右側にある複数の一致です。
次のコマンドについて考えてみます。出力は、すべての左側のリストと右側のリストの外部生成であることがわかります。
jq -cn '1,2,3| . == (1,1,3)'
true
true
false
false
false
false
false
false
true
その述語がselectステートメントにある場合、述語がtrueのときに入力を保持します。ここでも入力を複製できることに注意してください。
jq -cn '1,2,3| select(. == (1,1,3))'
1
1
3