簡體   English   中英

jq:從對象中選擇鍵的子集

[英]jq: selecting a subset of keys from an object

給定來自數組的鍵的輸入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'

任何想法如何清理這個?

我覺得從嵌套的JSON對象中提取選定的屬性與jq是一個很好的起點,但我無法讓它工作。

您可以使用此過濾器:

with_entries(
    select(
        .key as $k | any($keys | fromjson[]; . == $k)
    )
)

內部檢查的解決方案:

jq 'with_entries(select([.key] | inside(["key1", "key2"])))'

傑夫的回答有兩個不必要的低效率,假設使用--argjson keys而不是--arg keys ,以下兩個都解決了這個問題:

with_entries( select( .key as $k | $keys | index($k) ) )

內部操作員大部分時間都在工作; 但是,我剛發現內部操作符有副作用,有時它選擇了不需要的鍵,假設輸入為{ "key1": val1, "key2": val2, "key12": val12 }並由inside(["key12"])選擇inside(["key12"])它將同時選擇"key1""key12"

如果需要完全匹配,請使用in運算符:這樣只選擇.key2.key12

jq 'with_entries(select(.key | in({"key2":1, "key12":1})))'

因為in運算符只檢查來自對象的鍵(或者索引是否exists?於數組中),所以它必須用對象語法編寫,所需的鍵作為鍵,但值無關緊要; 使用in運算符並不是一個完美的用於此目的,我希望看到Javascript ES6包含API的反向版本,以實現為jq builtin

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/includes

jq 'with_entries(select(.key | included(["key2", "key12"])))'

檢查項目.key是否included? 從一個數組

這是一些額外的澄清

對於輸入對象{"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 entries命令可能有點棘手但很容易記住它需要一個過濾器並定義如下

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語句中,我們在謂詞為真時保持輸入。 請注意,您也可以在此處復制輸入。

jq -cn '1,2,3| select(. == (1,1,3))'
1
1
3

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM