중복된 키를 사용하여 주어진 입력 형식으로 입력합니다.
[
{"key": "a", "value": 0},
{"key": "a", "value": 1},
{"key": "a", "value": 2},
{"key": "b", "value": 3},
{"key": "b", "value": 4},
{"key": "b", "value": 5}
]
나는 생산하고 싶다
{"a": [0, 1, 2], "b": [3, 4, 5]}
즉, 각 고유 키에 대해 동일한 키를 가진 모든 값이 배열에 수집됩니다.
어떻게 해야 합니까 jq
?
답변1
reduce()
값으로 제공된 키에 지정된 값을 추가하여 결과 개체를 점진적으로 빌드하려면 in을 사용합니다 jq
.value
key
$ jq -c 'reduce .[] as $a ({}; .[$a.key] += [$a.value])' file
{"a":[0,1,2],"b":[3,4,5]}
이는 reduce()
루프처럼 동작합니다. 이 경우에는 .[]
최상위 배열의 모든 객체를 반복합니다. 각 객체에 대해 키 아래의 결과 객체(처음에는 빈 객체) $a
에 값이 추가됩니다 .$a.value
{}
$a.key
사용을 좋아하는 분들을 위한 추가 팁 jq
: 을 사용하면 debug
표현식이 실행되는 동안 표현식의 어느 지점에서나 데이터를 볼 수 있습니다. 여기서는 루프의 각 반복 후 누산기 개체의 상태를 살펴봅니다 reduce()
.
$ jq -c 'reduce .[] as $a ({}; .[$a.key] += [$a.value] | debug)' file
["DEBUG:",{"a":[0]}]
["DEBUG:",{"a":[0,1]}]
["DEBUG:",{"a":[0,1,2]}]
["DEBUG:",{"a":[0,1,2],"b":[3]}]
["DEBUG:",{"a":[0,1,2],"b":[3,4]}]
["DEBUG:",{"a":[0,1,2],"b":[3,4,5]}]
{"a":[0,1,2],"b":[3,4,5]}
$a
여기서는 각 반복에 할당된 값을 살펴보겠습니다.
$ jq -c 'reduce (.[]|debug) as $a ({}; .[$a.key] += [$a.value])' file
["DEBUG:",{"key":"a","value":0}]
["DEBUG:",{"key":"a","value":1}]
["DEBUG:",{"key":"a","value":2}]
["DEBUG:",{"key":"b","value":3}]
["DEBUG:",{"key":"b","value":4}]
["DEBUG:",{"key":"b","value":5}]
{"a":[0,1,2],"b":[3,4,5]}
답변2
group_by
, map
을 사용할 수 있습니다 .from_entries
jq 'group_by(.key) | map({key: .[0].key, value: [.[].value]}) | from_entries' data.json
답변3
프로그래밍 언어를 이미 알고 있다면 매우 구체적인 언어를 사용할 필요 없이 쉽게 선택할 수 있습니다 jq
. 그리고 perl
:
$ perl -MJSON -l -0777 -ne '
for (@{decode_json$_}) {push @{$out->{$_->{key}}}, $_->{value}}
print encode_json $out' your-file.json
{"a":[0,1,2],"b":[3,4,5]}
답변4
사용행복하다(이전 Perl_6)
JSON 파서를 사용해야 합니다.
~$ raku -MJSON::Tiny -e 'my @json = from-json($_).list given slurp; \
my %accum.push: .<key> => .<value>.map(*.Num).Slip for @json>>.split(", "); \
.say for to-json(%accum.sort);' file
입력 예:
[
{"key": "a", "value": 0},
{"key": "a", "value": 1},
{"key": "a", "value": 2},
{"key": "b", "value": 3},
{"key": "b", "value": 4},
{"key": "b", "value": 5}
]
출력 예(값이 Num
-ified 및 Slip
ped, 즉 평면화됨):
[ { "a" : [ 0, 1, 2 ] }, { "b" : [ 3, 4, 5 ] } ]
마지막 코드는 to-json()
끝에 호출을 추가합니다. 아마도 중간 단계에서 무슨 일이 일어나고 있는지 파악하는 가장 쉬운 방법은 각 개별 데이터 구조의 출력을 보여주는 것입니다. @json
배열을 인쇄하면 .say for @json;
다음이 반환됩니다.
{key => a, value => 0}
{key => a, value => 1}
{key => a, value => 2}
{key => b, value => 3}
{key => b, value => 4}
{key => b, value => 5}
%accum
다음을 호출하여 생성된 해시를 사용 .<key> => .<value>
(즉, 사용하지 않음)하면 .map(*.Num).Slip
다음을 반환할 수 있습니다 .say for %accum.sort;
.
[ { "a" : [ [ "0" ], [ "1" ], [ "2" ] ] }, { "b" : [ [ "3" ], [ "4" ], [ "5" ] ] } ]
Num
상단에 게시된 것과 같은 코드를 호출하면 Int
, "Flatten" 등의 함수 호출을 사용하여 값에 대해 다양한 작업을 수행할 수 있다는 점 참고하세요 .Slip
Raku의 JSON::Tiny
모듈은 기본적으로 값을 문자열화합니다. 이러한 문자열화된 값을 (하위 목록이 아닌) 단일 목록으로 원하는 경우 Slip
함께 묶습니다.
아래에서는 문자열화된 값이 Slip
결합됩니다.
~$ raku -MJSON::Tiny -e 'my @json = from-json($_).list given slurp; \
my %accum.push: .<key> => .<value>.Slip for @json>>.split(", "); \
.say for to-json(%accum.sort);' file
[ { "a" : [ "0", "1", "2" ] }, { "b" : [ "3", "4", "5" ] } ]
따라서 여기에는 데이터 출력을 위한 많은 옵션이 있습니다. 가장 간단한 것은 상단에 있는 코드를 가져와서 마지막 to-json()
호출을 제거하여 Raku의 %accum
해시 "쌍" 표현을 확인하는 것입니다.
a => [0 1 2]
b => [3 4 5]