조건에 따라 배열 요소의 위치를 변경하고 싶습니다(배열 요소의 인덱스 변경). 이것을 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- 마스터의 상대 위치는 동일하게 유지됩니다(A - C - B).
2- 동일한 유형의 비마스터의 상대 위치는 동일하게 유지됩니다.
(이 문제는 알고리즘 문헌에 이름이 있는 것 같아요? 내부 정렬?)
답변1
방법:
마스터 목록을 가져오고 해당 유형을 추출합니다. 이 순서 세트는 나머지 데이터를 어떤 순서로 처리할지 알려줍니다.
( .[] | select(.role == "master").type )
주어진 데이터에 대해 이는 집합
"A"
,"C"
, 입니다"B"
.이 컬렉션을 반복하여 마스터 역할이 있는 해당 유형의 요소를 추출한 다음 해당 유형은 있지만 마스터 역할이 없는 요소를 추출합니다.
루프는
$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]
역할이 있는 요소를 포함하는 두 부분으로 분할하는 것으로 시작됩니다.
그런 다음 in의 주요 요소를 반복하여 현재 유형에 해당하는 요소를 선택합니다 .[1]
..[0]
$master
각 기본 요소 뒤에 기본이 아닌 요소가 오는 배열을 만듭니다.