jq で関数を定義してマップを使用する

jq で関数を定義してマップを使用する

次の 2 つの違いを説明していただけますか?

jq ´def addvalue(f): . + [f]; map(addvalue(.[0]))´

[[1,2],[10,20]]
=> [[1,2,1], [10,20,10]]

jq ´def addvalue(f): f as $x | map(. + $x); addvalue(.[0])´
[[1,2],[10,20]]
=> [[1,2,1,2], [10,20,1,2]]

ありがとう。

答え1

要約: 2つの関数とそれらの呼び出し方法は、演算map()が行われる場所と加算で使用されるものが異なります。これは、最初のケースでは、map()呼び出しの関数内の加算が最初の要素を使用するため重要です。それぞれのサブ配列入力配列の。2番目のケースでは、map()関数内で実行され、加算は最初のサブ配列全体入力配列の。


最初の関数では、

def addvalue(f): . + [f];

入力ストリーム内の配列であると想定されるものに配列を追加します[f]。配列を別の配列に追加すると、配列に新しい要素が追加されます。

addvalue()この関数はmap()、配列[1,2]とのそれぞれに対して 1 回ずつ、 を使って 2 回呼び出します[10,20]。最初の呼び出しでは[f]が となる[1]ため、1最初の配列に新しい要素として を追加して を生成します。同様に、が である場合、2 回目の呼び出しから[1,2,1]が得られます。[10,20,10][f][10]

関数にデバッグを追加すると、

def addvalue(f): debug | . + [f]

質問のように呼び出すと、次のようになります。

["DEBUG:",[1,2]]
["DEBUG:",[10,20]]

これは、関数が 2 回呼び出されていることを示しています。最初の呼び出しでは値がに[f]なり[1]、演算 の結果[1,2] + [1]、 が与えられ[1,2,1][10]2 番目の呼び出しでは値が になり、[10,20] + [10]が与えられます[10,20,10]map()呼び出し内の演算により、これらの配列が に結合されます[[1,2,1],[10,20,10]]


関数内で

def addvalue(f): f as $x | map(. + $x);

map()入力ストリーム内の配列であると想定されるものを呼び出します。入力配列内の各要素に対して$x、その要素を追加します。 の値は、$x配列の最初の要素です。

[[1,2],[10,20]]この関数は、配列を入力配列、 を引数として1 回呼び出します[1,2]。入力配列の各要素、つまり[1,2]とに対して、 (配列の最初の要素 の値)[10,20]を追加します。配列を別の配列に追加すると、配列の要素が互いに追加されるため、結果の配列の 2 つの要素としてと が残ります。[1,2]$x[1,2,1,2][10,20,1,2]

最初の関数と同様に2番目の関数でもデバッグを有効にすると、

def addvalue(f): debug | f as $x | map(. + $x);

出力として得られる

["DEBUG:",[[1,2],[10,20]]]

これは、関数が 1 回呼び出されることを示しています。この操作により、入力配列の各要素がそれ自体に加算されたmap()配列が作成され、結果として返されます。[1,2][[1,2,1,2],[10,20,1,2]]


最初の関数を2番目の関数として動作させるには、次のように呼び出す必要があります。

.[0] as $x | map(addvalue($x[]))

2番目の関数を最初の関数のように動作させるには、次のように呼び出す必要があります。

[ .[] as $x | [$x] | addvalue([$x[0]]) | add ]

関連情報