Sort
如何使用 jq 有條件地重新定位 json 數組的元素?
我想根據條件重新定位數組的元素(更改數組元素的索引)。我不知道如何將它翻譯成 jq,它更像是一種功能語言。
基本上我想對數組進行排序,但特定元素的相對位置應該保持不變。
for each element: if element.role==master => record type for each element: if element.type == recorded type reposition the element to be below its master of similar type
我可以用一個例子更好地解釋。考慮
input.json
。如何在不改變相同類型的非主元素的相對位置的情況下將所有類型為“x”的非主元素移動到其主元素下方。(忽略“num”參數。僅用於顯示相對性)輸入.json
[ { "type": "A", "role": "master" }, { "num": 1, "type": "A" }, { "type": "C", "role": "master" }, { "num": 4, "type": "B" }, { "num": 2, "type": "B" }, { "type": "B", "role": "master" }, { "num": 3, "type": "B" }, { "num": 4, "type": "A" }, { "num": 2, "type": "A" }, { "num": 0, "type": "C" }, { "num": 5, "type": "C" }, { "num": 1, "type": "A" }, { "num": 1, "type": "B" } ]
目標.json
[ { "type": "A", "role": "master" }, { "num": 1, "type": "A" }, { "num": 4, "type": "A" }, { "num": 2, "type": "A" }, { "num": 1, "type": "A" }, { "type": "C", "role": "master" }, { "num": 0, "type": "C" }, { "num": 5, "type": "C" }, { "type": "B", "role": "master" }, { "num": 4, "type": "B" }, { "num": 2, "type": "B" }, { "num": 3, "type": "B" }, { "num": 1, "type": "B" } ]
如您所見:
1- master 的相對位置保持不變(A - C - B)
2- 相同類型的 non-master 的相對位置保持不變。
(我猜這個問題在算法文獻中有名字?就地排序?)
方法:
- 獲取 master 列表並提取它們的類型。這個有序集告訴我們以什麼順序處理其餘數據。
( .[] | select(.role == "master").type )
對於給定的數據,這是集合
"A"
,"C"
,"B"
. 2. 循環遍歷該集合併提取具有該類型且具有主角色角色的元素,然後是具有該類型且不具有主角色角色的元素。循環使用
$type
作為循環變數完成( .[] | select(.role == "master").type ) as $type
我們提取主人,然後是非主人:
( .[] | select(.type == $type and .role == "master" ) ), ( .[] | select(.type == $type and .role != "master" ) )
- 將所有內容放入數組中。這涉及到放置所有
[
東西]
。我們最終得到
[ ( .[] | select(.role == "master").type ) as $type | ( .[] | select(.type == $type and .role == "master" ) ), ( .[] | select(.type == $type and .role != "master" ) ) ]
這裡真的沒有排序。我們只是以有序的方式提取數據並從中創建一個新數組。
替代方法:首先從數組中提取整個主元素,而不僅僅是它們的類型:
[ ( .[] | select(.role == "master") ) as $master | $master, ( .[] | select(.type == $master.type and .role != "master" ) ) ]
另一種方法:首先使用初始數組的分組將主元素與其他元素分開。這假設只有元素具有
master
角色或根本沒有角色。group_by(.role) | [ .[1][] as $master | $master, ( .[0][] | select(.type == $master.type ) ]
這裡的第一行首先將原始數組分為兩部分,
.[0]
有沒有角色的元素,有有角色的元素.[1]
。然後我們遍歷主元素
.[1]
並從中選擇與.[0]
目前$master
類型相對應的元素。創建一個數組,其中每個主元素依次跟隨非主元素。